Qual è lo scopo del primo argomento per selezionare la chiamata di sistema?


25

A partire dal man select

int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

nfds è il descrittore di file con il numero più alto in uno dei tre set, più 1.

Qual è lo scopo nfds, quando abbiamo già readfds, writefdse exceptfds, da cui è possibile determinare i descrittori di file?


Stavo per chiedere informazioni su SO, ma qui è più centralizzato e le chiamate API C sono considerate in argomento .
phunehehe,

Risposte:


25

In "Advanced Programming in the UNIX Environment" , W. Richard Stevens afferma che si tratta di un'ottimizzazione delle prestazioni:

Specificando il descrittore più alto a cui siamo interessati, il kernel può evitare di passare attraverso centinaia di bit inutilizzati nei tre set di descrittori, cercando i bit che sono attivati.

(1a edizione, pagina 399)

Se stai eseguendo qualsiasi tipo di programmazione di sistemi UNIX, il libro APUE è altamente raccomandato.


AGGIORNARE

Di fd_setsolito è in grado di tracciare fino a 1024 descrittori di file.

Il modo più efficiente per tenere traccia di quali fdssono impostati 0e su cui è impostato 1sarebbe un bitset, quindi ciascuno fd_setconsisterebbe in 1024 bit.

Su un sistema a 32 bit, un int lungo (o "parola") è 32 bit, quindi ciò significa che ciascuno fd_setè
1024/32 = 32 parole.

Se nfdsè qualcosa di piccolo, come 8 o 16, che sarebbe in molte applicazioni, deve solo guardare dentro la prima parola, che dovrebbe essere chiaramente più veloce di guardare dentro tutti e 32.

(Vedi FD_SETSIZEe __NFDBITSda /usr/include/sys/select.hper i valori sulla tua piattaforma.)


AGGIORNAMENTO 2

Sul motivo per cui la firma della funzione non lo è

int select(fd_set *readfds, int nreadfds,
           fd_set *writefds, int nwritefds,
           fd_set *exceptfds, int nexceptfds,
           struct timeval *timeout);

La mia ipotesi è che il codice tenti di mantenere tutti gli argomenti nei registri , in modo che la CPU possa lavorare su di essi più velocemente e se dovesse tenere traccia di altre 2 variabili, la CPU potrebbe non avere abbastanza registri.

Quindi, in altre parole, selectsta esponendo un dettaglio di implementazione in modo che possa essere più veloce.


2
Quello, o il più recente The Linux Programming Interface
chris,

Anche APUE è stato aggiornato di recente. Seconda edizione: amazon.com/gp/aw/d.html/ref=aw_d_detail?pd=1&a=0201433079
Mikel

@chris Controllerò l'interfaccia di programmazione Linux. Grazie.
Mikel,

Grazie per le informazioni, controllerò i libri quando avrò un po 'di tempo.
phunehehe,

APUE 2nd Ed: 27 giugno 2005 (copre linux-2.4.22) TLPI: ottobre 2010 (copre linux-2.6.35)
chris

6

Non lo so per certo, dal momento che non sono uno dei progettisti di select (), ma direi che è un'ottimizzazione delle prestazioni. La funzione di chiamata sa quanti descrittori di file ha messo in lettura, scrittura e ad eccezione degli FD, quindi perché il kernel dovrebbe capirlo di nuovo?

Ricorda che nei primi anni '80, quando è stato introdotto select (), non avevano multi-gigaghertz, multi-processori con cui lavorare. Un VAX a 25 MHz era piuttosto veloce. Inoltre, volevi che select () funzionasse velocemente se potesse: se alcuni I / O stavano aspettando il processo, perché attendere che il processo attenda?


Alla tua tesi direi che ne abbiamo bisogno nreadfds, nwritefdse nexceptfdsnon solo uno nfds.
phunehehe,

Forse è così che nfdspuò andare in un registro per un accesso più veloce. Se dovesse tenere traccia di tre numeri, insieme a tutti gli altri argomenti, forse la CPU non avrebbe abbastanza registri. Naturalmente, il kernel avrebbe potuto crearne uno proprio nfdssulla base delle tue ipotetiche 3 variabili. Quindi la mia ipotesi è che sta esponendo un dettaglio di implementazione per ottenere efficienza.
Mikel,

@Mikel, phunehehe: nfdsargomenti separati porterebbero pochissimo guadagno. Il più delle volte, il processo ha aperto pochissimi processi rispetto a FD_SETSIZE. Un caso tipico potrebbe avere (4,4,2) su 1024; fare il check del kernel (4,4,4) è una grande vittoria (1024,1024,1024), ma l'ottimizzazione fino a (4,4,2) sarebbe quasi inutile.
Gilles 'SO- smetti di essere malvagio' il

@Gilles: il guadagno sarebbe un'API più pulita. (Così com'è, o il programmatore deve fare il lavoro extra per calcolare nfds, o essere pigro e chiamare select(FD_SETSIZE, ...), il che sarebbe più lento.)
Mikel

OTOH, il monitoraggio di una sola variabile massima potrebbe essere più semplice anche per il programmatore.
Mikel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.