选择系统调用的第一个参数的目的是什么?


25

man select

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

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

是什么目的nfds,当我们已经有了readfdswritefds并且exceptfds,从可确定的文件描述符?


我本来要问SO的问题,但在这里要集中得多,并且C API调用被认为是on-topic
phunehehe

Answers:


25

“UNIX环境高级编程”,理查德·史蒂文斯说,这是一个性能优化:

通过指定我们感兴趣的最高描述符,内核可以避免遍历三个描述符集中的一百个未使用的位,寻找打开的位。

(第1版,第399页)

如果您要进行任何类型的UNIX系统编程,强烈建议您阅读APUE。


更新

一个fd_set通常能够追踪多达1024个文件描述符。

跟踪fds设置为0和设置为的最有效方法是位集1,因此每个fd_set位都包含1024位。

在32位系统上,long int(或“ word”)为32位,因此意味着每个in​​t fd_set
1024/32 = 32个字。

如果nfds在某些应用程序中会用到较小的值(例如8或16),则只需要查看第一个单词的内部,显然应该比查看全部32个单词的速度快。

(请参见FD_SETSIZE__NFDBITS从中/usr/include/sys/select.h获取平台上的值。)


更新2

至于为什么功能签名不是

int select(fd_set *readfds, int nreadfds,
           fd_set *writefds, int nwritefds,
           fd_set *exceptfds, int nexceptfds,
           struct timeval *timeout);

我的猜测是,因为代码试图将所有参数保留在寄存器中,所以CPU可以更快地对其进行处理,并且如果必须跟踪额外的2个变量,则CPU可能没有足够的寄存器。

因此,换句话说,select是公开一个实现细节,以便可以更快。


2
那,或者更新的The Linux Programming Interface
chris

APUE最近也进行了更新。第二版:amazon.com/gp/aw/d.html/ref=aw_d_detail?pd = 1&a = 0201433079
Mikel

@chris我将检查Linux编程接口。谢谢。
Mikel

感谢您提供的信息,我会在抽空时检查一下这些书。
phunehehe 2011年

APUE第二版:2005年6月27日(涵盖linux-2.4.22)TLPI:2010年10月(涵盖linux-2.6.35)
chris

6

我不确定,因为我不是select()的设计师之一,但我会说这是性能优化。调用函数知道它在读取,写入和FD之外放入了多少个文件描述符,那么内核为什么还要重新找出它呢?

请记住,在80年代初引入select()时,他们没有多千兆赫,多处理器可以使用。25 MHz的VAX速度很快。另外,如果可能,您希望select()快速运行:如果某些I / O正在等待进程,为什么要让进程等待?


关于您的争论,我要说我们需要nreadfdsnwritefdsnexceptfds不是一个nfds
phunehehe 2011年

也许这样nfds可以将其放入寄存器中以加快访问速度。如果必须跟踪三个数字以及所有其他参数,则可能CPU将没有足够的寄存器。当然,内核可以nfds根据您的假设3个变量创建自己的内核。因此,我的猜测是它公开了实现细节以提高效率。
Mikel

@ Mikel,phunehehe:单独的nfds论点不会带来什么好处。在大多数情况下,该流程相对于而言打开的流程很少FD_SETSIZE。典型情况下,可能有(4,4,2)个,即1024个;进行内核检查(4,4,4)是(1024,1024,1024)的重大胜利,但优化到(4,4,2)几乎是无用的。
吉尔(Gilles)“所以,别再邪恶了”,

@Gilles:获得的收益将是更清洁的API。(按原样,程序员必须要做额外的工作才能计算nfds,或者懒得打电话select(FD_SETSIZE, ...),这会比较慢。)
Mikel

OTOH,对于程序员来说,仅跟踪一个最大变量也可能更容易。
Mikel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.