Em "Programação Avançada no Ambiente UNIX" , W. Richard Stevens diz que é uma otimização de desempenho:
Ao especificar o descritor mais alto em que estamos interessados, o kernel pode evitar passar por centenas de bits não utilizados nos três conjuntos de descritores, procurando por bits que estão ativados.
(1ª edição, página 399)
Se você estiver fazendo algum tipo de programação de sistemas UNIX, o manual do APUE é altamente recomendado.
ATUALIZAR
Um fd_set
é geralmente capaz de rastrear até 1024 descritores de arquivos.
A maneira mais eficiente para controlar quais fds
estão definidas para 0
e que são definidas como 1
seria uma bitset, de modo que cada fd_set
consistiria de 1024 bits.
Em um sistema de 32 bits, um int longo (ou "palavra") é de 32 bits, o que significa que cada um fd_set
é
1024/32 = 32 palavras.
Se nfds
for algo pequeno, como 8 ou 16, o que seria em muitas aplicações, ele precisa apenas olhar dentro da 1ª palavra, que deve ser claramente mais rápida do que dentro de 32.
(Veja FD_SETSIZE
e __NFDBITS
de /usr/include/sys/select.h
para os valores em sua plataforma.)
ATUALIZAÇÃO 2
Por que a assinatura da função não é
int select(fd_set *readfds, int nreadfds,
fd_set *writefds, int nwritefds,
fd_set *exceptfds, int nexceptfds,
struct timeval *timeout);
Meu palpite é que, porque o código tenta manter todos os argumentos nos registros , para que a CPU possa trabalhar neles mais rapidamente e, se tivesse que rastrear duas variáveis extras, a CPU talvez não tivesse registros suficientes.
Portanto, em outras palavras, select
está expondo um detalhe de implementação para que seja mais rápido.