【问题标题】:Query on Select System Call查询选择系统调用
【发布时间】:2009-03-13 19:59:18
【问题描述】:

select() 定义为:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);

nfds 表示所有给定集中的最高文件描述符加一。我想知道当 fd_set 信息可用时,为什么 select() 需要这些数据。

如果集合中的 FD 是 4、8、9,则 nfds 的值为 10。 select() 会监控 fds 9,8,7,6,5,4 ?

【问题讨论】:

    标签: c sockets


    【解决方案1】:

    问题在于 fd_set 并不是您所想的真正的“集合”。幕后细节是 fd_set 的实现只是一个用作位域的整数。也就是说,执行

    fd_set foo;
    FD_CLEAR(&foo);
    FD_SET(&foo, 3);
    

    将 foo 设置为十进制值 8 - 它将第四个最低有效位设置为 1(请记住 0 是有效的描述符)。

    FD_SET(&foo, 3);
    

    等价于

    foo |= (1 << 3);
    

    所以为了让 select 正常工作,它需要知道 fd_set 的哪些位是您关心的位。否则,它将无法告诉“在”集合中的零位,但从“不在”集合中的零位设置为 false。

    在您的示例中,具有 4、8 和 9 集且 n = 10 的 fd_set 被解释为“具有 10 个条目的集合 (fds 0-9)。条目 4、8 和 9 为真(监控它们) . 条目 1,2,3,5,6,7 是假的(不要监控它们)。任何大于 9 的 fd 值根本不在设定的时间段内。”

    【讨论】:

    • 但是int的位数是32,但是怎么监控任何大于31的fd
    • 有人可以回答这个评论吗?
    • @Shishir:Posix 将fd_set 定义为一个结构。内部是实现定义的,但一个流行的实现是结构包含一个长数组,数组中有足够的位来覆盖所有可能的 fd。这是因为 Posix 还要求 open 返回“编号最小的未使用文件描述符”。因此,除非您打开了 FD_SETSIZE 文件,否则您不会超出数组的范围。 pubs.opengroup.org/onlinepubs/007904975/basedefs/sys/…
    • @Shishir: 实际上 FD_SET(&foo, 3) 等价于 foo |= (1
    • 不应该是FD_SET(3, &amp;foo)吗?
    【解决方案2】:

    Select 监视您使用 FD_SET 宏启用的那些 FD。如果不启用任何 FD 进行监控,则 select() 不会监控任何 FD。

    “nfds”肯定是多余的,但它是select()接口的一部分,所以你需要使用它:)

    无论如何,如果集合中有 {4, 8, 9},则将 nfds 设置为 10(如您所述),并且 select() 将仅监视三个 FD 4、8 和 9。

    【讨论】:

      【解决方案3】:

      这可能是一种优化,因此select 不必遍历整个fd_set 来找出实际使用的描述符。如果没有该参数,select 将始终需要查看整个集合以查找调用中实际使用了哪些描述符,使用该参数,可以省略一些工作。

      【讨论】:

        猜你喜欢
        • 2021-11-07
        • 2021-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-11
        • 2010-10-09
        相关资源
        最近更新 更多