究竟是select()函数的第一个参数

时间:2014-07-02 19:01:53

标签: c linux sockets unix

我不太了解select函数中第一个参数的用途。 Wikipedia将其描述为所有集合中的最大文件描述符加1。为什么+1以及为什么select需要此信息?

4 个答案:

答案 0 :(得分:5)

在* Nix系统中,文件描述符只是系统表的索引,fd_set结构包含与这些索引对应的位掩码。将描述符添加到fd_set时,将启用相应的位。 select()需要知道最高描述符值,以便它可以遍历这些位并知道要停在哪一位。

在Windows上,套接字由内核对象的句柄表示,而不是由索引表示。 fd_set结构包含一个套接字句柄数组和一个数组中套接字数量的计数器。这样,select()可以循环遍历数组,这就是为什么在Windows上忽略select()的第一个参数的原因。

答案 1 :(得分:3)

这是(原始)伯克利套接字实现的偶然细节。基本上,该实现使用文件描述符的 number 作为一些临时内部位数组的大小调整变量。由于Unix描述符从零开始,因此最大描述符将比具有每个描述符一个插槽语义的任何数组的 size 小一个。因此,“最大加一”的要求。这个加1调整本来可以吸收到系统调用本身,但事实并非如此。

古代历史,就是这样。结果是第一个参数的正确解释与描述符的关系不如它们的(即要测试的最大描述符数)。参见Stevens et al的第6.3节(这是Rich Stevens经典文本的修订和更新版本。如果你没有它,那就去吧!)

答案 2 :(得分:1)

ideia是select函数可以使用第一个参数来优化读取fd_set的时序。

在手册中:

man select

它说:

  

nfds是三组中任何一组中编号最高的文件描述符,加上1。

因此select函数只检查fd_set中小于此值的fds,而不检查fd_set中所有可能的fds。此大小在FD_SETSIZE常量中定义。

答案 3 :(得分:1)

在大多数UNIX内核ABI中,fd_set *的{​​{1}}参数实际上是selectunsigned *,指向包含位的字数组。 unsigned long *的第一个参数告诉内核这些数组有多大以及应该检查多少位。

每个字包含16或18或32或36或64位(取决于机器的字大小);内核将使用最后一个单词中的select个低位(以及其他单词的所有位)从用户空间读取nfds/wordsize个单词。

POSIX引入了nfds%wordsize数据结构和相关函数,可以轻松管理这些位集,这些位集也可以移植到使用其他表示和内核ABI级别的其他系统。