【问题标题】:why do I need to update nfds in select call when I remove fds from master set?当我从主集中删除 fds 时,为什么我需要在 select 调用中更新 nfds?
【发布时间】:2015-06-09 22:32:31
【问题描述】:

给定这样的选择调用:

select(fdMax+1, &readFds, NULL, NULL, &timeoutVal)

readFds 随时更新的地方

  • 添加了新的 fd
  • 现有 fd 已删除

每当添加新的 fd 时,我都会更新 fdMax。但是,每当删除现有的 fd 时,我想知道 if I really need to update the fdMax also

如果我有更高的 fdMax 而没有足够的 fds 来阅读会有什么不同?

【问题讨论】:

  • 值得注意的是,您几乎应该始终使用poll(POSIX)或特定于操作系统的东西,例如epollkqueue
  • @o11c:select 的内核实现相当高效。依赖于select 的用户代码经常维护自己的活动文件描述符“稀疏数组”,他们将这些文件描述符与返回的集合进行比较以避免使用while (fd < fdMax) FD_ISSET(++fd, &readfds) 遍历集合,而是使用while (i < fdCount) FD_ISSET(fds[++i], &readfds)
  • @jxh 我使用:: 来划分这个函数在我的c++代码中的全局命名空间中。

标签: c sockets select


【解决方案1】:

您可以将fdMax 设置为系统支持的最大文件描述符值(可能由FD_SETSIZE 表示),不必担心,但这可能会导致效率低下。 select 将使用 fdMax 值作为何时可以停止对文件描述符表的线性扫描的提示。如果你对select 撒谎,它可能会导致它循环的时间比查找感兴趣的文件描述符实际需要的时间长得多。

在 Linux 中,函数 max_select_fd 使用 fdMax 开始反向扫描相关文件描述符。LXR

在 FreeBSD 中,如果 fdMax 较大,函数 kern_select 会将 fdMax 调整为进程的最高打开文件描述符。FXR 对于纯服务器,这看起来是一个很好的启发式选择,但对于一个小心地将套接字文件描述符保持在低于其他文件描述符的值的系统来说,它可能仍然太大。

【讨论】:

  • FD_SETSIZEfd_set 中位数组的大小。
  • @o11c:谢谢,我已经调整了答案。这有时只是提供给某些数组声明的常量,在这样的系统上,通过将 FD_SETSIZE 重新定义为更大的值来增加 select 可以处理的文件描述符的数量是“可能的”。
  • 是的,我已经做到了(也可以说你应该始终 setrlimit(RLIMIT_NOFILE) 到当前 TU 的 FD_SETSIZE)。但无论您是否重新定义了它,在任何给定的 TU 中,它都将与您的 fd_set 的大小相匹配。当然,有不同的定义不同的TU只是自找麻烦,它确实属于CPPFLAGS
【解决方案2】:

您可以使用一个预定义的符号 (maxfd)。然后无论实际使用的 FD 数量如何,都不必修改该参数。

【讨论】:

  • 我从来没有听说过这个,它肯定不在我的 libc 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 2015-04-21
  • 2012-08-02
  • 1970-01-01
相关资源
最近更新 更多