如何使用 epoll_select 和 EPOLLET 读取多个文件描述符?
题
男人epoll:
The suggested way to use epoll as an edge-triggered (EPOLLET) interface is as follows:
i with nonblocking file descriptors; and
ii by waiting for an event only after read(2) or write(2) return EAGAIN.
假设我们有两个 fd:第一个是被动的,数据仅有时可用,第二个是主动的,数据仅有时不可用。
epoll_wait 返回我们可以读取两者。我们在循环中读取{第一个,而不是第二个}(没有调用epoll_wait,因为它可能会在数据仍然可用时突然阻塞)。
现在,第一个文件描述符在读取时返回 EAGAIN。
该怎么办?
- 如果我们继续循环读取第二个 fd(不调用 epoll_wait),我们可能会错过第一个 fd 上的数据已变得可用。它只会不断地读、读、读,而无需 EAGAIN。
- 如果我们在每次从第二个 fd 读取之前“咨询”epoll_wait,epoll_wait 可能会突然阻塞,因为上次调用没有任何变化(数据在第一个 FD 上仍然不可用,但在第二个 FD 上仍然可用)。
如何继续处理第二个 FD,但又不忘记第一个 FD?
更新: 又发现一件事:男人epoll_wait:
while specifying timeout equal to zero makes epoll_wait() to return immediately even if no events are available
这样,即使没有事件,我也可以枚举 FD 的事件。
解决方案
如果 FD2 始终可读,您可能会认为 epoll 不适合它。或许值得抽出一条线索来坐下来阅读它。
否则,在循环中读取 FD2,直到其耗尽,但在循环中尝试每 X 次读取 FD1 一次。如果FD1有数据,则读取它。如果没有,您将得到 EAGAIN,重置 X 计数器并返回读取 FD2。当两者都耗尽时,您将回到 epoll_wait。
就像是:
count = 1;
while (true)
{
read fd2;
if (EAGAIN)
break;
else
process data;
count--;
if (! count)
{
while (true)
{
read fd1;
if (EAGAIN)
count = 10;
break;
else
process data;
}
}
}
不隶属于 StackOverflow