我们应该使用poll()还是select() ?

Shall we use poll() or select()?

本文关键字:还是 select poll 我们      更新时间:2023-10-16

我很清楚poll()select()的主要区别:

  • select()只支持固定数量的文件描述符
  • select()应该支持更多的系统
  • poll()允许对事件类型进行更细粒度的控制
  • poll()实现可能在某些细节上有所不同

然而,它们都以大致相同的方式完成相同的任务。所以:

我们应该使用poll()还是select() ?


EDIT:我可能会补充说,我对epoll()不感兴趣,因为可移植性是我关心的。此外,libev(ent)也不是一个选项,因为我问这个问题是因为我正在为libev(ent)编写自己的替代库。

所有远程现代系统都有poll,它在几乎所有方面都比select/pselect优越得多:

  • poll允许比select更细粒度的状态检测。
  • poll对您可以使用的最大文件描述符没有限制(更重要的是,当您未能检查超过FD_SETSIZE限制的文件描述符时,没有严重漏洞)。

我能想到使用poll的唯一缺点是:

  • 不像pselect, poll不能自动取消掩码/掩码信号,所以你不能用它来等待一组事件,包括文件描述符活动和信号,除非你诉诸自管道技巧。
  • poll只有毫秒级的等待超时分辨率,而不是微秒(select)或纳秒(pselect)。

当然poll的可移植性不再是一个考虑因素。任何旧到没有poll的系统都充满了如此多的漏洞,它不应该连接到网络。

总之,除非你有非常特殊的需求(微小的超时间隔、讨厌的信号交互、扩展到数百万个持久连接等),否则我会简单地使用poll并完成它。正如其他人提到的,libevent也是一种选择,但它不是干净/安全的代码(它使用select实际上调用了危险的UB,试图绕过select的限制!),我发现使用libevent的代码通常比直接使用poll的代码要复杂得多。

如果你是为GNU/Linux编写代码,你应该看看epoll(7)。

但是对于大多数跨平台支持,您可以考虑使用libevent。http://libevent.org/

实际上,在不了解您要做的具体操作的情况下,很难推荐单个轮询/选择实现。

我实际上推荐boost::asio,然后您可以尝试两种实现并测试,看看哪种最适合您的设置

我会使用libev或libevent。这些库是跨平台的,并且抽象了底层实现的细节(例如poll, select)

根据您的确切需求,我推荐poll::boost::asio。我发现libevent有点麻烦,它里面有各种面向C和/或面向更高级别协议处理的东西。

我不推荐select。我看到过select的实现因为超出描述符限制而以奇怪的方式无形地失败。你能做的就是让它以一种明显的方式失败。对于您的应用程序,这可能不太可能,但我不会冒险。

现在poll几乎可以在select的任何地方使用。唯一不是这样的地方是Windows。但是,我的意思是,如果你想跨平台移植到那个平台,你最好使用像::boost::asio这样的包装器,它很好地包装了最有效的操作系统技术。

苹果公司的民意调查()在TTYs, IME方面遇到了麻烦。在关注可移植性的情况下,select()可能是更好的选择。