答案1
好吧,七年后,我有一个更令人信服的答案,基于本文作者:埃文·克利茨克(Evan Klitzke)。
首先,我首先提出这个问题的原因是经常提到的epoll
与poll
/相比的性能优势select
。有句话说,epoll
(O(1)) 比poll
(O(否))。
不太为人所知的是边缘触发 epoll
确实是 O(1),而电平触发 epoll
具有与 O 相同的渐近性(否)。 的确,电平触发每次调用时,flavor 都必须仔细检查监视的 fds 列表,以找到可能仍有更多待处理数据的 fds。边缘触发多样性可以依靠信号来响应 fd 中出现的新字节。
有趣的是,找出恢复的线程究竟如何找出唤醒它的 fd,但在 epoll 触发唤醒期间传递这个数据肯定是可能的。
显然,poll
/select
不能使用边缘触发 epoll
因为语义不同。正如我们所见,使用电平触发 epoll
不会带来渐进的性能优势。而且,如果常数因子或常数项很高,也可能会对它产生负面影响(因为它们似乎基于我所做的并在另一条评论中引用的粗略基准)。
欲了解更多信息,请阅读阻塞 I/O、非阻塞 I/O 和 Epoll。
答案2
对于简单情况,poll 更简单;对于少量文件描述符,它可能同样高效。调用者无需担心维护 poll FD 和添加/删除 FD,他们只需在每次调用 poll 时添加他们想要的所有 FD 即可。
我的感觉是它们是互补的,尽管 poll 可以作为 epoll 的包装器来实现,但可能不应该这样。
epoll 可以(几乎)作为 poll 的包装器来实现,但是这会破坏它的效率论点。
答案3
poll()
和的语义epoll
不同。如果poll()
通知您描述符可读,则您进行一些读取但不要读取所有可用字节,然后poll()
再次将该描述符传入,它将立即唤醒。据我所知, 并非如此epoll
。
还要注意,epoll
描述符是一种有限的资源。 手册页谈论据epoll_create()
我所知不会发生的失败情况poll()
。
虽然我不确定所有的实现细节,但从中我们可以说,为 制作poll()
包装器是没有意义的epoll
。程序员必须意识到这些要点,并且使用poll()
允许的假设编写的现有代码将会被破坏。