以下内容是基于Linux-5.4.1记录
1.睡眠队列
static inline wait_queue_head_t *sk_sleep(struct sock *sk)
{
BUILD_BUG_ON(offsetof(struct socket_wq, wait) != 0);
return &rcu_dereference_raw(sk->sk_wq)->wait;
}
static inline void sock_poll_wait(struct file *filp, struct socket *sock,
poll_table *p)
{
if (!poll_does_not_wait(p)) {
poll_wait(filp, &sock->wq.wait, p);
}
}
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
if (p && p->_qproc && wait_address)
p->_qproc(filp, wait_address, p);
}
void sock_init_data(struct socket *sock, struct sock *sk)
{
if (sock) {
RCU_INIT_POINTER(sk->sk_wq, &sock->wq);
}
}
2.TCP
(1)accept睡眠
int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen, int flags)
{
err = sock->ops->accept(sock, newsock, sock->file->f_flags, false);
}
int inet_accept(struct socket *sock, struct socket *newsock, int flags,
bool kern)
{
struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err, kern);
}
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern)
{
error = inet_csk_wait_for_connect(sk, timeo);
}
static int inet_csk_wait_for_connect(struct sock *sk, long timeo)
{
for (;;) {
prepare_to_wait_exclusive(sk_sleep(sk), &wait,TASK_INTERRUPTIBLE);
if (reqsk_queue_empty(&icsk->icsk_accept_queue)){
timeo = schedule_timeout(timeo);
}
}
}
(2)TCP poll
__poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
{
sock_poll_wait(file, sock, wait);
}
3.epoll
(1)睡眠过程
(2)poll过程
static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
struct file *tfile, int fd, int full_check)
{
init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);
revents = ep_item_poll(epi, &epq.pt, 1);
}
static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
{
pt->_qproc = qproc;
pt->_key = ~(__poll_t)0; /* all events enabled */
}
static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
poll_table *pt)
{
struct epitem *epi = ep_item_from_epqueue(pt);
struct eppoll_entry *pwq;
if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, GFP_KERNEL))) {
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
pwq->whead = whead;
pwq->base = epi;
if (epi->event.events & EPOLLEXCLUSIVE)
add_wait_queue_exclusive(whead, &pwq->wait);
else
add_wait_queue(whead, &pwq->wait);
list_add_tail(&pwq->llink, &epi->pwqlist);
epi->nwait++;
} else {
/* We have to signal that an error occurred */
epi->nwait = -1;
}
}
static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
{
wake_up(&ep->wq);
}
Jan 24 14:09:28 chro kernel: [ 12.698552] Call Trace:
Jan 24 14:09:28 chro kernel: [ 12.698553] dump_stack+0x6d/0x95
Jan 24 14:09:28 chro kernel: [ 12.698554] tcp_poll+0x1fb/0x2b0
Jan 24 14:09:28 chro kernel: [ 12.698555] sock_poll+0x79/0xb0
Jan 24 14:09:28 chro kernel: [ 12.698556] ep_item_poll.isra.16+0x43/0xc0
Jan 24 14:09:28 chro kernel: [ 12.698557] ep_insert+0x119/0x4a0
Jan 24 14:09:28 chro kernel: [ 12.698558] ? ep_show_fdinfo+0xa0/0xa0
Jan 24 14:09:28 chro kernel: [ 12.698559] __x64_sys_epoll_ctl+0x568/0x600
Jan 24 14:09:28 chro kernel: [ 12.698560] ? __x64_sys_epoll_ctl+0x568/0x600
Jan 24 14:09:28 chro kernel: [ 12.698562] do_syscall_64+0x57/0x190
Jan 24 14:09:28 chro kernel: [ 12.698563] entry_SYSCALL_64_after_hwframe+0x44/0xa9
在ep_insert通过ep_item_poll-->tcp_poll-->sock_poll_wait-->poll_wait(filp, &sock->wq.wait, p);把sock->wq.wait睡眠队列与ep_poll_callback注册在一起
所以当有数据来的时候
Jan 24 14:11:13 chro kernel: [ 118.403071] dump_stack+0x6d/0x95
Jan 24 14:11:13 chro kernel: [ 118.403072] ep_poll_callback+0x2cf/0x2e0
Jan 24 14:11:13 chro kernel: [ 118.403074] ? ksize+0x19/0x30
Jan 24 14:11:13 chro kernel: [ 118.403074] __wake_up_common+0x73/0x120
Jan 24 14:11:13 chro kernel: [ 118.403075] __wake_up_common_lock+0x7e/0xc0
Jan 24 14:11:13 chro kernel: [ 118.403076] __wake_up_sync_key+0x1e/0x30
Jan 24 14:11:13 chro kernel: [ 118.403076] sock_def_readable+0x40/0x70
Jan 24 14:11:13 chro kernel: [ 118.403078] unix_stream_sendmsg+0x271/0x390
Jan 24 14:11:13 chro kernel: [ 118.403079] sock_sendmsg+0x63/0x70
Jan 24 14:11:13 chro kernel: [ 118.403080] sock_write_iter+0x8c/0xf0
Jan 24 14:11:13 chro kernel: [ 118.403082] do_iter_readv_writev+0x159/0x1d0
Jan 24 14:11:13 chro kernel: [ 118.403083] do_iter_write+0x86/0x1a0
Jan 24 14:11:13 chro kernel: [ 118.403083] vfs_writev+0x92/0x120
Jan 24 14:11:13 chro kernel: [ 118.403106] ? tty_ldisc_deref+0x16/0x20
Jan 24 14:11:13 chro kernel: [ 118.403107] ? tty_read+0x9d/0xf0
Jan 24 14:11:13 chro kernel: [ 118.403108] ? __vfs_read+0x1b/0x40
Jan 24 14:11:13 chro kernel: [ 118.403109] do_writev+0xde/0x120
Jan 24 14:11:13 chro kernel: [ 118.403109] ? do_writev+0xde/0x120
Jan 24 14:11:13 chro kernel: [ 118.403110] __x64_sys_writev+0x1c/0x20
Jan 24 14:11:13 chro kernel: [ 118.403111] do_syscall_64+0x57/0x190
Jan 24 14:11:13 chro kernel: [ 118.403112] entry_SYSCALL_64_after_hwframe+0x44/0xa9
Jan 24 14:11:13 chro kernel: [ 118.403184] dump_stack+0x6d/0x95
Jan 24 14:11:13 chro kernel: [ 118.403185] ep_poll+0x46f/0x490
Jan 24 14:11:13 chro kernel: [ 118.403187] ? wake_up_q+0x80/0x80
Jan 24 14:11:13 chro kernel: [ 118.403188] do_epoll_wait+0xb0/0xc0
Jan 24 14:11:13 chro kernel: [ 118.403189] __x64_sys_epoll_wait+0x1e/0x30
Jan 24 14:11:13 chro kernel: [ 118.403191] do_syscall_64+0x57/0x190
Jan 24 14:11:13 chro kernel: [ 118.403217] entry_SYSCALL_64_after_hwframe+0x44/0xa9
static void sock_def_readable(struct sock *sk)
{
struct socket_wq *wq;
rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, EPOLLIN | EPOLLPRI |
EPOLLRDNORM | EPOLLRDBAND);
sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
rcu_read_unlock();
}
阅读(706) | 评论(0) | 转发(0) |