epoll能否保证在使用epoll_ctl注册文件时,对于EPOLLIN和EPOLLET的第一次(或持续性)调用epoll_wait会立即返回,如果在epoll_ctl调用之前文件已经可读?通过我的测试程序的实验,答案似乎是肯定的。以下是几个示例以澄清我的问题:
假设我们已初始化了一个epoll文件efd
和文件fd
,并且定义了以下事件:
event.data.fd = fd;
event.events = EPOLLIN | EPOLLET;
现在考虑以下情况:
- 线程1:向
fd
写入数据 - 线程2:
epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
- 线程2:
epoll_wait (efd, events, MAXEVENTS, -1);
现在考虑第二种情况,扩展第一种情况:
- 线程1:向
fd
写入数据 - 线程2:
epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
- 线程2:
epoll_wait (efd, events, MAXEVENTS, -1);
- 线程2:
epoll_ctl (efd, EPOLL_CTL_MOD, fd, &event);
- 线程2:
epoll_wait (efd, events, MAXEVENTS, -1);
epoll手册对此问题并不完全清楚。特别是手册建议,在使用边缘触发模式时,应始终从文件中读取,直到返回EAGAIN。但似乎这些注释假定您在每次想要等待文件时不会重新注册文件。
相关讨论可以参考epoll的边缘触发选项的目的是什么?。第一个答案的前两个评论似乎证实了我看到的行为是预期的。 https://gist.github.com/3900742 是一个C测试程序,说明使用管道的epoll似乎就是我所描述的。
/* 如果文件已经“准备就绪”,我们将其放入准备就绪列表中 */
if ((revents & event->events) && !ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
- Andreas