【发布时间】:2016-07-18 02:06:06
【问题描述】:
文档不清楚事件是否被合并,我的测试表明它们在某些情况下但并非总是如此。
考虑man 7 epoll:
由于即使使用边缘触发的 epoll,在接收到多个数据块时也可以生成多个事件,调用者已经 指定 EPOLLONESHOT 标志的选项...
以及问答部分:
Q7 如果 epoll_wait(2) 调用之间发生多个事件,是合并还是单独报告?
A7 它们将被合并。
我假设手册中的第一条语句意味着在从套接字读取、数据包到达、您读取它、然后另一个数据包到达等情况下,您可以接收多个 EPOLLIN 事件。 Q&A 部分的答案是讨论不同的事件,如 EPOLLIN 和 EPOLLOUT。如果我错了,请纠正我。
为了更好地理解 epoll 是如何工作的,我正在玩一些代码,并且它似乎在基于是否设置了另一个事件的情况下对相同类型的事件表现不同。更准确地说,如果我只等待 EPOLLIN,则多个输入会生成一个事件,但如果我同时等待 EPOLLIN 和 EPOLLOUT,则多个输入会生成多个事件。
这是我用来测试的代码:
#include <stdio.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
struct epoll_event ev = {EPOLLIN|EPOLLOUT|EPOLLET};
int epoll = epoll_create1(0);
epoll_ctl(epoll, EPOLL_CTL_ADD, 0, &ev);
//async stdin
int flags = fcntl(0, F_GETFL);
flags |= O_NONBLOCK;
fcntl(0, F_SETFL, flags);
while(1){
struct epoll_event events[64];
int n = epoll_wait(epoll, events, 64, -1);
printf("Event count: %d\n", n);
if(events[0].events == EPOLLIN)
printf("EPOLLIN only\n\n");
else
if(events[0].events == (EPOLLIN|EPOLLOUT))
printf("EPOLLIN and EPOLLOUT\n\n");
else
printf("EPOLLOUT only\n\n");
char buffer[256];
read(0, buffer, 256);
sleep(1);
}
return 0;
}
按回车后的输出显示EPOLLIN和EPOLLOUT都收到了,这个信息出现的次数与按回车的次数一样多,然后显示只有EPOLLOUT正在生成。
但是如果你在编译程序时不带EPOLLOUT标志并多次按return,那么单个事件将只报告一次。
如果我删除 read 调用,则在设置 EPOLLOUT 时会继续报告 EPOLLIN,但在仅设置 EPOLLIN 时不会报告。
行为取决于它正在等待的事件还是我的测试代码有问题?如果它是依赖的,我可以放心它将来不会改变吗?
【问题讨论】:
-
简而言之,您通过在只读文件描述符上请求
EPOLLOUT通知来滥用epollAPI。我已经提供了完整的答案。