【问题标题】:What exactly is the first argument of select() functionselect() 函数的第一个参数究竟是什么
【发布时间】:2014-08-23 17:04:26
【问题描述】:

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

【问题讨论】:

  • 也许它需要抵消它,因为它认为有效的文件描述符编号来自1 to n,而不是0 to (n - 1)。

标签: c linux sockets unix


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 加 1 是有道理的。感谢您的回答和链接。如果我理解了 Remy Lebeau 的回答和你的回答,内部位数组是否包含在添加描述符时启用的位元素?
    • 在最初的伯克利实现中,内部位数组为每个系统调用重新组装。跨调用不维护任何状态。 Rich Stevens 也报道了血淋淋的细节,here
    【解决方案3】:

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

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

    【讨论】:

    • 那作者为什么不把fd_set做成链表呢?
    【解决方案4】:

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

    在手册中:

    man select
    

    上面写着:

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

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

    【讨论】:

    • 这毫无意义。 fd_set 可以有多个值。如果select()“只检查fd_set中小于这个的fds,而不是fd_set中所有可能的fds”,它会跳过值。
    • @RemyLebeau nfds 应该是具有最大值 + 1 的文件描述符。即,如果将文件描述符 5、9、90 放在 fd_set 中,则将 nfd 参数设置为 91。任何文件您放置在 fd_set 中的描述符小于 91 - 您感兴趣的描述符都不会被跳过。
    • 我明白nfd 是什么。不过,请查看您的答案的措辞:“select 函数仅检查 fd_set 中小于此的 fds,而不是 fd_set 中所有可能的 fds”。这意味着可以跳过添加到 fd_set 的值。只需修改您的措辞,以更清楚地说明select() 不会检查所有可能的 fd,只是实际添加到 fd_set 中的 fd。
    • 好吧,如果您添加具有值 >= nfds 参数的描述符,则确实会跳过描述符,
    猜你喜欢
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 2021-08-03
    • 2017-04-25
    • 1970-01-01
    相关资源
    最近更新 更多