Epoll Manpage说,如果未完成阅读,则在Epollet(Edge触发)注册的FD不应两次通知Epollin。
因此,在Epollin之后,您需要在Epoll_Wait能够在新数据上返回新的Epollin之前清空缓冲区。

但是,我正在遇到这种方法问题,因为我看到了重复的Epollin事件,可用于未受感染的FD。
这是strace输出,0x200是epollrdhup,在我的glibc标题中尚未定义,但在内核中定义。

30285 epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET|0x2000, {u32=9, u64=9}}) = 0
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3, {{EPOLLIN, {u32=9, u64=9}}}, 10, -1) = 1
30285 epoll_wait(3,  <unfinished ...>
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = 0
30306 recv(9, "7u\0\0\10\345\241\312\t\20\f\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30"..., 20000, 0) = 20000
30349 epoll_ctl(3, EPOLL_CTL_DEL, 9, NULL) = -1 ENOENT (No such file or directory)
30305 recv(9, " \31(C0\17\32\r\10\27\20\2\30\200\10 \31(C0\17\32\r\10\27\20\2\30\200\10 \31("..., 20000, 0) = 10011

因此,在添加FD号9后,我确实会在恢复文件描述符之前接收2个连续的Epollin事件,Syscall Trace显示了我在阅读之前的删除FD的方式,但每次事件只能发生一次。
因此,我要么不正确阅读该手册,要么现在在这里工作。

有帮助吗?

解决方案

我想你错过了这一部分 epoll 男人页:

由于在收到多个数据时也可以生成边缘触发的EPOLL多个事件,但呼叫者可以选择指定该数据 EPOLLONESHOT 标志,告诉epoll接收到事件后,禁用关联的文件描述符 epoll_wait(2). 。当。。。的时候 EPOLLONESHOT 指定标志,使用呼叫者有责任使用文件描述符。 epoll_ctl(2)EPOLL_CTL_MOD.

也就是说:您在第一次之前有两个数据到达接收队列 read() 发生了,这意味着您有两个Epoll事件。这好像是 EPOLLONESHOT 是您所追求的,当事件发生时,它会从原子上删除文件描述符(因此您无需执行 EPOLL_CTL_DEL).

其他提示

Edge Trigger只是指(除非您使用过Epolloneshot),当某些东西进入(内核)缓冲区时,您将获得1个事件。

因此,如果您获得了1个Epollin事件,并且对此一无所获,那么下次有些数据到达该描述符时,您将获得另一个epollin - 如果没有新的数据到达,即使您没有获得事件,即使您没有进行事件读取第一个事件所示的任何数据。

好吧,简洁地说,epolloneshot只是意味着,如果您不阅读应该阅读的数据,它们将被丢弃。

通常,如果您不读取相同的数据,就会通知您的事件。但是,使用epolloneshot,不阅读数据是完全合法的,他们将被忽略。因此,不会生成其他事件。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top