1

我一直在阅读libev 的源代码,偶然发现了这个评论:

a) epoll 默默地从 fd 集中删除 fds。因为没有任何东西告诉我们一个 fd 已经被移除,所以我们必须不断地“重新武装”我们怀疑可能已经改变的 fd(与 kqueue 相同的问题,但那里的成本要低得多)。

我一直在一些现代 linux 内核上使用 epoll(直接使用系统调用)进行一些测试,但我无法重现它。我没有看到“默默消失的 fds”有任何问题。有人可以详细说明一下并告诉我这是否仍然是一个问题?

4

1 回答 1

3

这是相当模糊的文本,但我想这只是如果描述符在close其他地方是 d ,它会被默默地从集合中删除。来自 Linux 联机帮助页,epoll(7)

Q6 关闭一个文件描述符会导致它自动从所有 epoll 集中移除吗?

A6 可以,但请注意以下几点。文件描述符是对打开文件描述的引用(请参阅 参考资料open(2))。每当通过 dup(2)dup2(2)fcntl(2) F_DUPFD或复制描述符时fork(2),都会创建一个引用相同打开文件描述的新文件描述符。一个打开的文件描述会继续存在,直到所有引用它的文件描述符都已关闭。只有在引用底层打开文件描述的所有文件描述符都已关闭之后(或者在使用显式删除描述符之前,文件描述符才会从 epoll 集中删除) epoll_ctl(2) EPOLL_CTL_DEL)。这意味着即使在作为 epoll 集的一部分的文件描述符已经关闭之后,如果引用相同底层文件描述的其他文件描述符仍然打开,则可能会报告该文件描述符的事件。

所以你有一个 fd 42 的套接字。它得到closed,然后从epoll对象中删除。但是内核不会libev通过. epoll_wait现在epoll_modify再次使用 fd = 调用42epoll_modify不知道这个文件描述符 42 是否与epoll对象中已经存在的相同,或者文件描述符编号为 42 的其他文件描述是否被重用。

人们也可能会争辩说,这些评论只是在咆哮,而libevAPI 的设计在这里有问题。

于 2017-10-28T08:23:58.110 回答