如果在边缘触发模式下调用epoll_ctl之前文件是可读的,后续的epoll_wait会立即返回吗?

时间:2012-10-16 17:27:31

标签: linux epoll

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

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

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

现在考虑这种情况:

  1. thread1:将数据写入fd
  2. thread2:epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
  3. thread2:epoll_wait (efd, events, MAXEVENTS, -1);
  4. 现在步骤3中的呼叫立即返回吗?根据我的经验,确实如此。这有保证吗?

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

    1. thread1:将数据写入fd
    2. thread2:epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
    3. thread2:epoll_wait (efd, events, MAXEVENTS, -1);
    4. thread2:epoll_ctl (efd, EPOLL_CTL_MOD, fd, &event);
    5. thread2:epoll_wait (efd, events, MAXEVENTS, -1);
    6. 第5步中的通话是否立即返回?根据我的经验,确实如此。有保证吗?

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

      what is the purpose of epoll's edge triggered option?是一个相关的讨论。对第一个答案的前两个评论似乎证实我看到的行为是预期的。

      https://gist.github.com/3900742是一个C测试程序,它说明带有管道的epoll似乎表现得像我所描述的那样。

1 个答案:

答案 0 :(得分:4)

由于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);

这样就解释了你所看到的行为,似乎是故意做的。但由于没有规范,因此没有铸铁保证未来的行为不会发生变化。