phu*_*ehe 25 system-calls file-descriptors
从 man select
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
Run Code Online (Sandbox Code Playgroud)
nfds 是三个集合中任何一个中编号最大的文件描述符,加 1。
的目的是什么nfds
,当我们已经有了readfds
,writefds
和exceptfds
,从中可以确定文件描述符?
Mik*_*kel 27
在“UNIX 环境中的高级编程”中,W. Richard Stevens 说这是一种性能优化:
通过指定我们感兴趣的最高描述符,内核可以避免遍历三个描述符集中的数百个未使用的位,寻找打开的位。
(第一版,第 399 页)
如果您正在从事任何类型的 UNIX 系统编程,强烈推荐 APUE 书籍。
更新
Anfd_set
通常能够跟踪多达 1024 个文件描述符。
跟踪哪些fds
设置为0
和哪些设置为的最有效方法是位集1
,因此每个fd_set
将包含 1024 位。
在 32 位系统上,long int(或“字”)是 32 位,这意味着每个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);
Run Code Online (Sandbox Code Playgroud)
我的猜测是因为代码试图将所有参数保存在registers 中,因此 CPU 可以更快地处理它们,如果它必须跟踪额外的 2 个变量,则 CPU 可能没有足够的寄存器。
换句话说,select
就是公开一个实现细节,以便它可以更快。
我不确定,因为我不是 select() 的设计者之一,但我会说这是一种性能优化。调用函数知道它在 read、write 和 except FD 中放入了多少文件描述符,那么内核为什么要再次计算出来呢?
请记住,在 80 年代初,当 select() 被引入时,他们没有可使用的多千兆赫兹、多处理器。25 MHz VAX 速度相当快。另外,如果可以的话,您希望 select() 快速工作:如果某些 I/O 正在等待进程,为什么要让进程等待?
归档时间: |
|
查看次数: |
6663 次 |
最近记录: |