8

epoll 是否保证在使用 epoll_ctl 为 EPOLLIN 注册文件后对 epoll_wait 的第一次(或正在进行的)调用,如果在 epoll_ctl 调用之前文件已经可读,则 EPOLLET 立即返回?从我对测试程序的实验来看,答案似乎是肯定的。这里有几个例子来澄清我的问题:

假设我们已经初始化了一个 epoll 文件efd和一个文件fd 以及如下事件定义:

event.data.fd = fd;
event.events  = EPOLLIN | EPOLLET;

现在考虑这种情况:

  1. thread1:写入数据fd
  2. 线程2:epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
  3. 线程2:epoll_wait (efd, events, MAXEVENTS, -1);

现在第 3 步中的调用会立即返回吗?根据我的经验,确实如此。这是有保证的吗?

现在考虑第二种情况,扩展第一种情况:

  1. thread1:写入数据fd
  2. 线程2:epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
  3. 线程2:epoll_wait (efd, events, MAXEVENTS, -1);
  4. 线程2:epoll_ctl (efd, EPOLL_CTL_MOD, fd, &event);
  5. 线程2:epoll_wait (efd, events, MAXEVENTS, -1);

步骤 5 中的调用是否立即返回?根据我的经验,确实如此。有保障吗?

epoll 手册页在这个问题上并不完全清楚。特别是,手册页建议您应该始终从文件中读取,直到使用边缘触发模式时返回 EAGAIN。但似乎这些评论是假设您在等待文件时没有重新注册文件。

epoll的边缘触发选项的目的是什么?是一个相关的讨论。第一个答案的前两条评论似乎证实了我看到的行为是预期的。

https://gist.github.com/3900742是一个 C 测试程序,它说明了带有管道的 epoll 的行为似乎与我描述的一样。

4

1 回答 1

5

由于epoll特定于 Linux 没有真正的规范,因此它几乎取决于实际实现的内容(手册页尝试以更用户友好的方式描述它,但不提供边缘情况的所有细节)。

查看ep_insertep_modify都检查当前事件位(与 无关EPOLLET):

/*
 * Get current event bits. We can safely use the file* here because
 * its usage count has been increased by the caller of this function.
 */
revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt);

所以这解释了你所看到的行为,它似乎是故意的。但是由于没有规范,因此无法保证将来行为不会改变。

于 2012-10-17T14:27:20.353 回答