В статье «Расширенное программирование в среде UNIX» Ричард Стивенс говорит, что это оптимизация производительности:
Указав самый высокий дескриптор, который нас интересует, ядро может избежать прохождения сотен неиспользуемых битов в трех наборах дескрипторов, ища биты, которые включены.
(1-е издание, стр. 399)
Если вы занимаетесь программированием любых систем UNIX, настоятельно рекомендуется книга APUE.
ОБНОВИТЬ
fd_set
, Как правило , в состоянии отслеживать до 1024 дескрипторов файлов.
Наиболее эффективный способ отследить, какие из fds
них установлены, 0
а какие установлены, - это набор битов 1
, поэтому каждый из них fd_set
будет состоять из 1024 битов.
В 32-битной системе long int (или «слово») составляет 32 бита, так что каждый из них fd_set
равен
1024/32 = 32 слова.
Если nfds
есть что-то маленькое, например, 8 или 16, которое было бы во многих приложениях, ему нужно только заглянуть внутрь 1-го слова, которое должно быть явно быстрее, чем заглянуть внутрь всех 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);
Я думаю, это потому, что код пытается сохранить все аргументы в регистрах , чтобы ЦПУ мог работать с ними быстрее, и если бы ему пришлось отслеживать дополнительные 2 переменные, ЦП может не иметь достаточно регистров.
Другими словами, select
раскрывает детали реализации, чтобы они могли быть быстрее.