这上面, 又分配了一个struct eppoll_entry结构. 其实它跟struct epitem 结构是一一对应的.
随后就是一些初始化
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback); // set func:ep_poll_callback
pwq->whead = whead;
pwq->base = epi;
add_wait_queue(whead, &pwq->wait)
list_add_tail(&pwq->llink, &epi->pwqlist);
epi->nwait++;
这其中相当重要的是设置pwd->wait.func = ep_poll_callback。
现在, struct epitem 和struct eppoll_entry的关系就像下面这种
![]()
对于TCP socket, 当收到对端报文后,最初设置的sk->sk_data_ready函数将被调用
void sock_init_data(struct socket *sock, struct sock *sk)
{
// code omitted...
sk->sk_data_ready = sock_def_readable;
// code omitted...
}
经过层层调用,最终会调用到 __wake_up_common 这上面会递归挂在socket.wq上的等待队列上的函数
static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
int nr_exclusive, int wake_flags, void *key)
{
wait_queue_t *curr, *next;
list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
unsigned flags = curr->flags;
if (curr->func(curr, mode, wake_flags, key) &&
(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
break;
}
}
于是, 顺着图中的这条黑色轨迹, 就会调用到我们设定的ep_poll_callback,那么接下去就是要让epoll实例才能知有文件早已可读了
先从入参中取出当前表项epi和ep
struct epitem *epi = ep_item_from_wait(wait);
struct eventpoll *ep = epi->ep;
再把epi挂到ep的就绪队列
if (!ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist)
}
接着唤醒阻塞在(如果有)该epoll实例的用户.
waitqueue_active(&ep->wq)
谁有也许阻塞在epoll实例的等待队列上呢? 当然就是使用epoll_wait来从epoll实例获取发生了感兴趣事件的的表述符的用户.
epoll_wait会读取到ep_poll()函数.
if (!ep_events_available(ep)) {
/*
* We don't have any available event to return to the caller.
* We need to sleep here, and we will be wake up by
* ep_poll_callback() when events will become available.
*/
init_waitqueue_entry(&wait, current);
__add_wait_queue_exclusive(&ep->wq, &wait);
如果没有事件,我们就将自己挂在epoll实例的期待队列上之后睡去.....
如果有事件,那么我们还要将事件返回给用户
ep_send_events(ep, events, maxevents)
the-implementation-of-epoll
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-139730-2.html
核潜艇国之利器
那就让女性无偿服务呀
五元一吨
可能是思维错了
你别说他幼稚