为什么必须在边缘触发epoll函数中使用非阻塞fd?

时间:2013-02-01 09:32:02

标签: linux socket.io nonblocking epoll

我在网上阅读了文档abount edge触发的epoll函数,如下所示:

1. The file descriptor that represents the read side of a pipe (rfd) is registered on the epoll instance.
2. A pipe writer writes 2 kB of data on the write side of the pipe.
3. A call to epoll_wait(2) is done that will return rfd as a ready file descriptor.
4. The pipe reader reads 1 kB of data from rfd.
5. A call to epoll_wait(2) is done.
.......
.......

将epoll用作边缘触发(EPOLLET)接口的建议方法如下:      i)使用非阻塞文件描述符     ii)只有在读取(2)或写入(2)返回EAGAIN后才调用epoll_wait。

我理解2,但我不知道为什么使用非阻塞文件描述符。

有人能解释使用非阻塞文件描述符的原因吗? 为什么在级别触发的epoll函数中使用阻塞文件描述符是可以的?

3 个答案:

答案 0 :(得分:5)

当您有边缘触发的通知表明存在数据时,我们的想法是尝试完全耗尽文件描述符。因此,一旦epoll()返回,您就会循环遍历read()write(),直到没有更多数据时它返回-EAGAIN

如果fd被阻止打开,那么最后read()write()也会被阻止,你就没有机会回到epoll()来等待整套fds。打开非阻止后,最后read() / write()会返回,您确实有机会返回投票。

在以级别触发的方式使用epoll()时,这并不是一个问题,因为在这种情况下,如果有任何数据,epoll()将立即返回有。所以(伪代码)循环如:

while (1) {
  epoll();
  do_read_write();
}

会有效,因为只要有数据,您就可以保证拨打do_read_write()。使用边缘触发的epoll时,如果在do_read_write()完成和下一次调用epoll()之间有新数据可用,则可能会有错误通知。

答案 1 :(得分:0)

我想这是因为边缘触发的语义。根据语义,边缘触发器仅在收到EAGAIN后才会引发另一个事件。在阻塞套接字的情况下,没有EAGAIN。您可以通过其他方式定义它,但这是Linux如何定义它。换句话说,如果使用阻塞套接字,则无法确定何时可以安全地调用epoll_wait。

答案 2 :(得分:0)

你必须在epoll的ET模式下读取全部或写入所有数据,因为在标志改变后触发了一次et模式。读取所有数据后,如果使用块读取或写入,则必须挂起该线程。因此必须使用非阻塞。