来自 epoll_wait 的 epoll 事件顺序

epoll order of events from epoll_wait

我已经将程序从 select 移植到 epoll 以增加我们可以处理的套接字数量。我已经把sockets加到epoll fd上了,可以愉快的读写了

但是,即使我使用的是级别触发事件,我还是担心套接字可能会耗尽。我担心的场景是当准备好的套接字多于 epoll_event 结构时。我知道下次我调用 epoll_wait 时它会给我其余的,但我想知道我让他们进入的顺序是什么,以确保上次和这次谁没有晋级。

一个例子: 假设我有 10 个套接字连接并添加到 epoll fd。我的内存只够 5 epoll_event 个结构。假设在每个 epoll_wait 之间的时间内,所有 10 个套接字都接收到数据。第一个 epoll_wait 将 return 5 epoll_event 结构进行处理,假设它是套接字 1-5。我处理了这 5 个套接字,在我这样做的同时,更多的数据进来了,所有 10 个套接字都有更多的数据要读取。我再次输入 epoll_wait 并得到 5 个 epoll_event 结构。

我的问题是在第二次调用 epoll_wait 时我将获得哪 5 个套接字。会不会是 sockets 1-5 因为它们首先被添加到 epoll FD?或者我会获得套接字 6-10,因为这些事件是在更多数据进入套接字 1-5 之前引发的吗?

本质上,epoll_wait 像一个 FIFO 队列,还是它只是扫描一个内部套接字列表(从而优先选择列表中的第一个套接字)。

编辑: 这是 Linux 内核 v4.9.62

仔细阅读 epoll 的源文件,可以看到就绪事件是在链表中维护的。事件从列表头部移除并添加到列表末尾。

基于此,答案是描述符顺序基于它们准备就绪的顺序。

@jxh 对这种行为的观察是正确的,而且这种行为早已确立(如果我没记错的话,多年前我与实施者 Davide Libenzi 的电子邮件对话就是最初的意图)。不幸的是,到目前为止它还没有被记录下来。但是,我已经为即将发布的手册页修复了该问题,其中 epoll_wait(2) 将包含文本:

If more than maxevents file descriptors are ready when epoll_wait() is called, then successive epoll_wait() calls will round robin through the set of ready file descriptors. This behavior helps avoid starvation scenarios, where a process fails to notice that additional file descriptors are ready because it focuses on a set of file descriptors that are already known to be ready.