System-Calls
選擇系統呼叫的第一個參數的目的是什麼?
從
man select
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
nfds 是三組中編號最高的文件描述符,加 1。
nfds
當我們已經有了和時readfds
,可以從中確定文件描述符的目的是什麼?writefds``exceptfds
在“UNIX 環境中的高級程式”中,W. Richard Stevens 說這是一種性能優化:
通過指定我們感興趣的最高描述符,核心可以避免遍曆三個描述符集中的數百個未使用位,尋找打開的位。
(第 1 版,第 399 頁)
如果您正在做任何類型的 UNIX 系統程式,強烈推薦 APUE 書。
更新
An
fd_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);
我的猜測是因為程式碼試圖將所有參數保存在寄存器中,因此 CPU 可以更快地處理它們,如果它必須跟踪額外的 2 個變數,CPU 可能沒有足夠的寄存器。
換句話說,
select
就是公開一個實現細節,以便它可以更快。
- BSD 4.4 Lite select 原始碼(select 和 selscan 函式)
- Linux 2.6.37 選擇原始碼(do_select 和 max_select_fd 函式)