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

use*_*694 4 linux epoll nonblocking socket.io

我在网上读了文件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.
.......
.......
Run Code Online (Sandbox Code Playgroud)

使用epoll作为边缘触发(EPOLLET)接口的建议方法如下:i)使用非阻塞文件描述符ii)仅在read(2)或write(2)返回EAGAIN之后为事件调用epoll_wait.

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

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

she*_*heu 7

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

如果fd被打开阻塞,那么最后read()或者write()也会阻塞,你将没有机会回到epoll()等待整个fds集的调用.当打开非阻塞时,最后read()/ write()确实返回,并且您确实有机会返回轮询.

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

while (1) {
  epoll();
  do_read_write();
}
Run Code Online (Sandbox Code Playgroud)

do_read_write()只要有数据,你就可以保证打电话.当使用边缘触发的epoll时,如果在完成do_read_write()和下一次调用之间进入,则有可能通知新数据可用epoll().

  • 这个答案的最后一部分似乎没有说到点子上。当您不等待时发生的事件也将被注册,并在下次运行 epoll_wait 时返回。但真正的问题是,如果你没有通过 do_read_write 函数从套接字读取所有数据,那么你会再次进入 epoll_wait 。然后,对于边缘触发的行为,您将无限期地陷入困境,因为只有在可读性(或可写性)发生变化时才会产生事件。问题不在于数据何时到来,而在于您没有全部读取它们。 (2认同)