使用libevent strace 结果分析2 epoll 间的相互监听
epoll作为一个文件既可以监视其他文件,也可以被其他epoll监视。这样就产生了一个监视的有向图。
ep_eventpoll_poll 文件的poll操作,也就是file->f_op->poll(). 调用该函数可以获取就绪文件的事件掩码,但是 epoll 文件只提供读就绪事件,并且读就绪事件是由非epoll文件的就绪事件决定的。也就是说当一个epoll文件被 select(2)/poll(2)/epoll(2) 监听时,必须该epoll已经监听了其他的非epoll文件(如eventfd), 在调用 该epoll file->f_op->poll() 时才可能返回可读的就绪事件。
static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests) { struct readyevents_arg *arg = priv; // 判断当前有没有事件触发 return ep_scan_ready_list(arg->ep, ep_read_events_proc, NULL, call_nests + 1, arg->locked); } static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) { int pollflags; struct eventpoll *ep = file->private_data;// 被监听的epoll struct readyevents_arg arg; /* * During ep_insert() we already hold the ep->mtx for the tfile. * Prevent re-aquisition. */ arg.locked = wait && (wait->_qproc == ep_ptable_queue_proc); arg.ep = ep; /* Insert inside our poll wait queue */ poll_wait(file, &ep->poll_wait, wait);//// 插入到wait_queue /* * Proceed to find out if wanted events are really available inside * the ready list. This need to be done under ep_call_nested() * supervision, since the call to f_op->poll() done on listed files * could re-enter here.、
// 扫描就绪的文件列表, 调用每个文件上的poll 检测是否真的就绪, // 然后复制到用户空间 // 文件列表中有可能有epoll文件, 调用poll的时候有可能会产生递归,
// 调用所以用ep_call_nested 包装一下, 防止死循环和过深的调用 */// 判断是否有事件触发 pollflags = ep_call_nested(&poll_readywalk_ncalls, EP_MAX_NESTS, ep_poll_readyevents_proc, &arg, ep, current); return pollflags != -1 ? pollflags : 0; }
ep_scan_ready_list以前分析过了,主要逻辑是在里面执行函数,ep_read_events_proc,我们看一下ep_read_events_proc是如何判断被监听的epoll中是否有事件触发的。
static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, void *priv) { struct epitem *epi, *tmp; poll_table pt; init_poll_funcptr(&pt, NULL); // 遍历就绪队列 list_for_each_entry_safe(epi, tmp, head, rdllink) { if (ep_item_poll(epi, &pt)) // ep_item_poll判断epitem中实现有事件触发 return POLLIN | POLLRDNORM; else { /* * Item has been dropped into the ready list by the poll * callback, but it's not actually ready, as far as * caller requested events goes. We can remove it here. */// 这个事件虽然在就绪列表中, // 但是实际上并没有就绪, 将他移除 // 这有可能是水平触发模式中没有将文件从就绪列表中移除 // 也可能是事件插入到就绪列表后有其他的线程对文件进行了操作 __pm_relax(ep_wakeup_source(epi)); list_del_init(&epi->rdllink); } } return 0; }
这个传入的参数head 是啥呢? 就是 ep->rdllist 也就是被监听的epoll中的rdlist 也就是被监听的epoll 中监听其他的tcp fd的就绪rdlist

以下是epoll 先关数据结构以及相互调用:


2、
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子

浙公网安备 33010602011771号