我一直在阅读libev's source code并偶然发现了这条评论:
a)epoll默默地从fd集中删除fds。因为没有告诉我们fd已被删除,否则我们必须不断“重新安置”我们怀疑可能已经改变的fds(与kqueue相同的问题,但那里的成本要低得多)。
我在一些现代的Linux内核上用epoll(直接使用系统调用)进行了一些测试,我无法重现它。我没有看到“默默地消失fds”的任何问题。有人可以详细说明这个并告诉我它是否仍然是一个问题?
答案 0 :(得分:3)
这是一个相当含糊的文本,但我想只是如果描述符在其他地方close
d,它会被静默地从集合中删除。从Linux联机帮助页epoll(7):
Q6 关闭文件描述符会导致它 从所有epoll集中自动删除?
A6 是的,但请注意以下几点。一份文件 descriptor是对打开文件的引用 描述(见
open(2)
)。每当一个描述符 通过dup(2)
,dup2(2)
,fcntl(2)
复制F_DUPFD
或fork(2)
,新的文件描述符引用 - 戒指到相同的打开文件描述是cre- ated。打开文件描述继续 存在直到引用它的所有文件描述符 已经关闭。删除文件描述符 从epoll设置后只有所有文件 描述符引用底层的打开文件 描述已被关闭(或之前,如果 描述符是使用显式删除的epoll_ctl(2)
EPOLL_CTL_DEL
)。这意味着 甚至在作为文件描述符的一部分之后 epoll set已关闭,可能会报告事件 对于该文件描述符,如果其他文件描述 - tors引用相同的底层文件 描述仍然开放。
所以你有一个fd 42的套接字。它得到close
d,然后从epoll
对象中删除。但是内核没有通过 libev
通知epoll_wait
关于此的内容。现在,使用fd = epoll_modify
再次调用42
。 epoll_modify
不知道此文件描述符42是否与epoll
对象中已有的文件描述符相同,或者是否重用了文件描述符编号为42的其他文件描述。
还有人可能会说这些评论只是咆哮而且libev
API的设计在这里是错误的。