select()定义为:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
nfds 表示所有给定集合中的最高文件描述符加1。我想知道为什么fd_set信息可用时select()需要这些数据。
如果集合中的FD是4,8,9,那么 nfds 的值将是10.将select()moniter fds 9,8,7,6,5,4 ?
答案 0 :(得分:8)
问题在于,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的哪些位是您关心的位。否则,它将无法告诉“在”集合中的零位,但是从“不在”集合中的零位设置为假。
在您的示例中,具有4,8和9集且n = 10的fd_set被解释为“具有10个条目的集合(fds 0-9)。条目4,8和9为真(监视它们) 。条目1,2,3,5,6,7是假的(不监视它们。)任何大于9的fd值都不在设定的时间内。“
答案 1 :(得分:0)
选择使用FD_SET宏监视已启用的FD。如果您没有启用任何FD进行监控,则select()不会监控任何FD。
“nfds”肯定是多余的,但它是select()接口的一部分,所以你需要使用它:)
无论如何,如果你在集合中有{4,8,9},你可以将nfds设置为10(正如你所提到的),而select()将只监视三个FD 4,8和9。
答案 2 :(得分:0)
这可能是一种优化,因此select
不必遍历整个fd_set
以找出实际使用的描述符。如果没有该参数,select
将始终需要查看整个集合以查找调用中实际使用的描述符,使用参数,可以省略其中一些工作。