7

我在 web 中阅读了文档 about 边缘触发的 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) 仅在 read(2) 或 write(2) 返回 EAGAIN 后调用 epoll_wait 事件。

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

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

4

3 回答 3

9

这个想法是当你有一个边缘触发的通知表明有数据需要时,尝试完全耗尽文件描述符。因此,一旦epoll()返回,您将遍历read()orwrite()直到-EAGAIN没有更多数据时它返回。

如果 fd 被打开阻塞,那么最后一个read()orwrite()也将阻塞,并且您将没有机会返回epoll()调用等待整个 fd 集。当以非阻塞方式打开时,最后一个read()/write()确实返回,并且您确实有机会返回轮询。

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

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

do_read_write()会起作用,因为只要有数据,您就可以保证调用。当使用边缘触发的 epoll 时,如果新数据出现在完成do_read_write()和下一次调用epoll().

于 2013-02-01T09:41:54.110 回答
0

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

于 2013-09-13T20:12:11.653 回答
0

epoll 的 ET 模式必须读取所有数据或写入所有数据,因为在 flag 更改后触发了一次 et 模式。当您读取所有数据后,如果您使用块读取或写入,则线程必须挂起。所以必须使用非阻塞。

于 2017-04-17T10:56:51.100 回答