我们应该使用poll()还是select() ?
Shall we use poll() or select()?
我很清楚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()可能是更好的选择。
- enum是C++中的宏变量还是整数变量
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 在命名空间中定义函数还是限定函数
- 架构决策:返回std::future还是提供回调
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 异常属于C++中的线程还是进程
- 在决定是通过参考还是通过价值时,尺寸真的是一个问题吗
- 如何在C++中确定文本文件中的元素是字符还是数字
- 返回值优化:显式移动还是隐式
- 是什么原因导致它无法编译?它是声明签名还是在函数本身的实现中
- 为什么需要知道一个类是平凡的还是有平凡的构造函数
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 'string.assign(string.data(), 5)' 是明确定义的还是 UB?
- 在哪里放置我的函数?进入我的母语 Gui 还是进入我的演示者?
- 在这种情况下,我真的复制了字节还是复制了字符?
- node-gyp 的先有鸡还是先有蛋的问题:指向依赖项中的头文件
- SQLite3 在 c++ 中输出 SELECT 上的空列表
- CIN是逻辑1还是0?
- i++还是++i更适合这个程序?
- 我们应该使用poll()还是select() ?