epoll的手册页有一个边缘触发的示例代码,如下所示:
for (;;) {
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_pwait");
exit(EXIT_FAILURE);
}
for (n = 0; n < nfds; ++n) {
if (events[n].data.fd == listen_sock) {
conn_sock = accept(listen_sock,
(struct sockaddr *) &local, &addrlen);
if (conn_sock == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
setnonblocking(conn_sock);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
&ev) == -1) {
perror("epoll_ctl: conn_sock");
exit(EXIT_FAILURE);
}
} else {
do_use_fd(events[n].data.fd);
}
}
}
在函数 do_use_fd 中,我在 while 循环中调用 nonblocked recv 直到 EAGAIN,示例代码工作正常。
我对这个示例代码有疑问,假设现在我有 50 个套接字客户端连接,突然有 10 个客户端同时写入数据,所以 epoll_wait() 将返回 10 然后进入 for 循环:
for (n = 0; n < nfds; ++n)
它将调用 do_use_fd(events[n].data.fd);
这 10 个客户端,假设 n=5 已完成,而 n=6 尚未完成,突然事件 n=3 的文件描述已收到新数据,在所有这 10 个事件完成后返回 epoll_wait ,我会收到通知我有客户有新数据要读取的事件吗?否则我会错过它,因为当事件发生时,代码不在 epoll_wait 中!