在一个无限循环中,我正在使用 select 监听 100 多个文件描述符。如果 fd 有一些数据包可供读取,我会通知分配给此文件描述符的数据包处理器线程,并且我不会为下一轮设置此文件描述符的位,直到我收到来自数据处理器线程的通知说它已完成. 我想知道如果我不计算最大值,我的代码会有多低效。每次我从集合中清除/设置文件描述符时选择 fd。我期望文件描述符几乎是连续的,每个 fd 的数据到达率是每秒几千字节。
2 回答
你真的应该使用poll
而不是select
. 两者都是标准的,但poll
更易于使用,不会限制您可以检查的文件描述符的数量(而select
将您限制为编译时常FD_SETSIZE
量),并且更有效。如果你使用select
,你总是可以传递FD_SETSIZE
第一个参数,但这当然会给出最坏情况下的性能,因为内核必须扫描整个fd_set
; 传递实际的 max+1 允许更短的搜索,但仍然不如传递给poll
.
epoll
就其价值而言,如今使用非标准 Linux或任何等效的 BSD似乎很时尚。如果您有大量(大约数万)长寿命(至少几次往返)连接,这些接口可能具有一些优势,但否则性能不会明显更好(并且,在较低端,可能更糟),这些接口当然是不可移植的,而且在我看来,比普通的、可移植的更难正确使用poll
。
原则上,提供一个好的 max fd 是很重要的select
(但在您的进程中只有几百个文件描述符并不重要)。
但是select
已经过时了(正是因为 max fd,所以内核将花费O(m)时间,其中m是 max.fd;所以如果在 max mselect
很大的一小组文件描述符上使用它可能会很昂贵) . 改用poll(2)(当给定一组n文件描述符时,它需要O(n)时间,与最大文件描述符m无关)。
当前的 Linux 系统和进程可能有成千上万的文件描述符。阅读有关C10K 问题的信息。
并且您可能有一些事件循环,例如使用libevent或libev之类的库(可能在poll
内部̀,并且可能使用更多操作系统特定的东西,例如epoll
等...在一个方便的界面中抽象它们)