epoll是否保留文件描述符注册的顺序?

8

我正在研究Linux系统调用,发现了一些epoll方面的问题让我感到困惑。比如,我创建了一个epoll实例:

epollfd = epoll_create(50);

下一步,我在for循环中注册了50个文件描述符:
for(i=0; i<50; i++){
    // open file "file-i".txt
    // construct epoll_event
    // register new file descriptor with epoll_ctl(epollfd, EPOLL_CTL_ADD ...

现在我们有50个文件,准备好进行操作(读或写--无所谓)。我们将MAX_EVENTS设置为3:

#define MAX_EVENTS 3
...
struct epoll_event events[MAX_EVENTS]
...
epoll_wait(epollfd, events, MAX_EVENTS, -1)

所有50个文件都已准备好,我们只需要其中的3个。哪些文件将在events数组中呢?
  • [1,2,3] -- 按照它们被添加到epoll的顺序,前三个文件
  • [48,49,50] -- 按照它们被添加到epoll的顺序,最后三个文件
  • [34, 7, 15] -- 随机选择3个文件
  • 其他任何选项
谢谢。
1个回答

8
浏览 epoll 的源文件,可以看到准备好的事件以链表的形式维护。事件从链表头部删除并添加到链表尾部。

基于此,答案是描述符的顺序是基于它们变为就绪状态的顺序。

这种行为现在已经记录在 epoll_wait 的注释中:

如果在调用 epoll_wait() 时有多于 maxevents 个文件描述符准备就绪,则连续的 epoll_wait() 调用将循环轮换遍历准备就绪的文件描述符集合。...

感谢@mtk提供的文档。


2
我还想补充一点,每个 CPU 上都持有一个 mtx 锁,因此如果在 MP 机器上出现 fd 同时可用的情况,那么获得锁的人将会是胜者。 - Ahmed Masud
@jxh,那么在我的情况下,如果我添加了50个准备好读/写的文件描述符,我会得到[1,2,3]吗? - Artem Mezhenin
@amezhenin 不一定......您无法保证读/写是按顺序进行的。您将获得50个描述符中前三个已准备好进行读写的描述符。 - Ahmed Masud
1
如果在添加描述符之前所有描述符都已准备好,并且您没有使用边缘触发行为,则我期望您按照添加它们的顺序获取描述符。对于边缘触发行为,我预计您将不会收到任何描述符,但我需要测试一下,因为这是一个边界条件,而poll可能会针对添加描述符的情况做出特殊处理。 - jxh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接