Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Epoll在EPOLLET模式下,从插槽读取前返回2个EPOLLIN_Linux_Networking_Epoll_Epollet - Fatal编程技术网

Linux Epoll在EPOLLET模式下,从插槽读取前返回2个EPOLLIN

Linux Epoll在EPOLLET模式下,从插槽读取前返回2个EPOLLIN,linux,networking,epoll,epollet,Linux,Networking,Epoll,Epollet,epoll手册页指出,如果未进行读取,则向EPOLLET(边缘触发)注册的fd不应通知EPOLLIN两次。 因此,在一个EPOLLIN之后,您需要在epoll_等待能够在新数据上返回一个新的EPOLLIN之前清空缓冲区 然而,我在使用这种方法时遇到了问题,因为我看到未接触fds的EPOLLIN事件重复。 这是strace输出,0x200是EPOLLRDHUP,它尚未在我的glibc头中定义,但在内核中定义 30285 epoll_ctl(3, EPOLL_CTL_ADD, 9, {EPOLLIN

epoll手册页指出,如果未进行读取,则向EPOLLET(边缘触发)注册的fd不应通知EPOLLIN两次。
因此,在一个EPOLLIN之后,您需要在epoll_等待能够在新数据上返回一个新的EPOLLIN之前清空缓冲区

然而,我在使用这种方法时遇到了问题,因为我看到未接触fds的EPOLLIN事件重复。
这是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
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_等待(3,
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 enoint(没有这样的文件或目录)
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
因此,在添加9号fd之后,在接收文件描述符之前,我确实收到了2个连续的EPOLLIN事件,系统调用跟踪显示了我如何在读取之前删除fd,但它应该只发生一次,每个事件一次。

因此,要么我没有正确阅读手册页,要么这里出现了问题。

我想你错过了
epoll
手册页的这一部分:

因为即使边缘被触发 epoll可以生成多个事件 在收到多块 数据,调用方可以选择 指定
epolonneshot
标志,以 告诉epoll禁用关联的 在收到文件后的文件描述符 带有
epoll\u wait(2)
的事件 指定了
epolonneshot
标志, 打电话的人有责任 使用以下命令重新排列文件描述符:
epoll\u ctl(2)
with
epoll\u ctl\u MOD

也就是说:在第一次
read()
发生之前,有两个数据块到达了接收队列,这意味着有两个epoll事件。您所追求的似乎是
EPOLLONESHOT
,当事件发生时,它将自动从轮询集中删除文件描述符(因此,您不需要执行
EPOLL\u CTL\u DEL
)。

边缘触发器只意味着(除非您使用了epolonneshot),当某些内容进入(内核)缓冲区时,您将获得1个事件


因此,如果您得到一个EPOLLIN事件,并且对它不做任何处理,那么下次一些数据到达该描述符时,您将得到另一个EPOLLIN-如果没有新数据到达,您将不会得到一个事件,即使您没有读取第一个事件指示的任何数据。

简单地说,EPOLLONESHOT只是意味着如果您没有读取您应该读取的数据将被丢弃


通常情况下,如果您不读取相同的数据,您会收到一个事件通知。但是,对于Eploneshot,不读取数据是完全合法的,它们将被忽略。因此,不会生成进一步的事件。

回答得好。我还有一个问题:如果设置了Eploneshot,是否需要Epllet?大多数情况下,当我们如果收到ePloloneshot事件,我们将执行IO,直到fd阻止我们的IO操作,然后我们将重新安装事件。