Desde man select
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
nfds es el descriptor de archivo con el número más alto en cualquiera de los tres conjuntos, más 1.
¿Cuál es el propósito nfds
, cuando ya lo tenemos readfds
, writefds
y exceptfds
de qué se pueden determinar los descriptores de archivos?
system-calls
file-descriptors
phunehehe
fuente
fuente
Respuestas:
En "Programación avanzada en el entorno UNIX" , W. Richard Stevens dice que es una optimización del rendimiento:
(1a edición, página 399)
Si está haciendo algún tipo de programación de sistemas UNIX, el libro APUE es muy recomendable.
ACTUALIZAR
Un
fd_set
generalmente puede rastrear hasta 1024 descriptores de archivo.La forma más eficiente de rastrear cuáles
fds
están configurados0
y cuáles están configurados1
sería un conjunto de bits, por lo que cada unofd_set
consistiría en 1024 bits.En un sistema de 32 bits, un int largo (o "palabra") es de 32 bits, lo que significa que cada uno
fd_set
es1024/32 = 32 palabras.
Si
nfds
es algo pequeño, como 8 o 16, que sería en muchas aplicaciones, solo necesita mirar dentro de la primera palabra, que claramente debería ser más rápido que mirar dentro de los 32.(Consulte
FD_SETSIZE
y__NFDBITS
desde/usr/include/sys/select.h
los valores de su plataforma).ACTUALIZACIÓN 2
En cuanto a por qué la firma de la función no es
Supongo que es porque el código intenta mantener todos los argumentos en los registros , por lo que la CPU puede trabajar en ellos más rápido, y si tuviera que rastrear 2 variables adicionales, la CPU podría no tener suficientes registros.
En otras palabras,
select
está exponiendo un detalle de implementación para que pueda ser más rápido.fuente
No estoy seguro, ya que no soy uno de los diseñadores de select (), pero diría que es una optimización del rendimiento. La función de llamada sabe cuántos descriptores de archivo pone en lectura, escritura y excepto FD, entonces, ¿por qué el núcleo debería resolverlo nuevamente?
Recuerde que a principios de los años 80, cuando se introdujo select (), no tenían multi-gigaghercios, multiprocesadores para trabajar. Un VAX de 25 MHz fue bastante rápido. Además, quería que select () funcionara rápido si pudiera: si alguna E / S estaba esperando el proceso, ¿por qué hacer que el proceso espere?
fuente
nreadfds
,nwritefds
y ennexceptfds
lugar de solo unonfds
.nfds
pueda ingresar en un registro para un acceso más rápido. Si tuviera que rastrear tres números, junto con todos los demás argumentos, tal vez la CPU no tendría suficientes registros. Por supuesto, el núcleo podría haber creado uno propionfds
basado en sus 3 variables hipotéticas. Entonces, supongo que está exponiendo un detalle de implementación para ganar eficiencia.nfds
argumentos separados traerían muy poca ganancia. La mayoría de las veces, el proceso ha abierto muy pocos procesos en relación conFD_SETSIZE
. Un caso típico podría tener (4,4,2) de 1024; hacer la verificación del kernel (4,4,4) es una gran victoria sobre (1024,1024,1024), pero la optimización hasta (4,4,2) sería casi inútil.nfds
, o ser flojo y llamarselect(FD_SETSIZE, ...)
, lo que sería más lento).