Von man select
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
nfds ist der Dateideskriptor mit der höchsten Nummer in einem der drei Sätze plus 1.
Wofür nfds
haben wir, wenn schon readfds
, writefds
und exceptfds
woraus können die Dateideskriptoren ermittelt werden?
system-calls
file-descriptors
phunehehe
quelle
quelle
Antworten:
In "Advanced Programming in the UNIX Environment" beschreibt W. Richard Stevens dies als eine Leistungsoptimierung:
(1. Auflage, Seite 399)
Wenn Sie UNIX-Systeme programmieren, wird das APUE-Buch dringend empfohlen.
AKTUALISIEREN
In der
fd_set
Regel können bis zu 1024 Dateideskriptoren verfolgt werden.Der effizienteste Weg zu verfolgen, auf welchen
fds
eingestellt ist0
und auf welche eingestellt ist,1
wäre ein Bitsatz, alsofd_set
würde jeder aus 1024 Bits bestehen.Auf einem 32-Bit - System, ein long int (oder "Wort") beträgt 32 Bits, so dass jeder daß Mittel
fd_set
ist1024/32 = 32 Worte.
Wenn
nfds
es sich bei etwas Kleinem wie 8 oder 16 handelt, wie es in vielen Anwendungen der Fall ist, muss nur das erste Wort gesucht werden, was eindeutig schneller sein sollte als alle 32.(Siehe
FD_SETSIZE
und__NFDBITS
von/usr/include/sys/select.h
für die Werte auf Ihrer Plattform.)UPDATE 2
Warum ist die Funktionssignatur nicht
Ich vermute, es liegt daran, dass der Code versucht, alle Argumente in Registern zu speichern , damit die CPU schneller mit ihnen arbeiten kann. Wenn zwei zusätzliche Variablen nachverfolgt werden müssten, verfügt die CPU möglicherweise nicht über genügend Register.
Mit anderen Worten,
select
wird ein Implementierungsdetail verfügbar gemacht, damit es schneller sein kann.quelle
Ich weiß es nicht genau, da ich nicht zu den Designern von select () gehöre, aber ich würde sagen, es ist eine Leistungsoptimierung. Die aufrufende Funktion weiß, wie viele Dateideskriptoren in die Lese-, Schreib- und Ausnahmen-FDs eingefügt wurden. Warum sollte der Kernel dies also erneut herausfinden?
Denken Sie daran, dass in den frühen 80er Jahren, als select () eingeführt wurde, keine Multi-Gigaghertz-Prozessoren zur Verfügung standen, mit denen gearbeitet werden konnte. Ein 25 MHz VAX war ziemlich schnell. Außerdem wollten Sie, dass select () schnell arbeitet, wenn dies möglich ist: Wenn einige E / A auf den Prozess warteten, warum sollte der Prozess warten?
quelle
nreadfds
,nwritefds
undnexceptfds
statt nur einemnfds
.nfds
man sich für einen schnelleren Zugriff registrieren kann. Wenn es drei Zahlen zusammen mit allen anderen Argumenten verfolgen müsste, hätte die CPU möglicherweise nicht genügend Register. Natürlich hätte der Kernelnfds
auf der Grundlage Ihrer hypothetischen 3 Variablen eine eigene erstellen können. Ich vermute also, dass ein Implementierungsdetail sichtbar gemacht wird, um die Effizienz zu steigern.nfds
Argumente würden sehr wenig Gewinn bringen. In den meisten Fällen hat der Prozess nur sehr wenige Prozesse in Bezug auf geöffnetFD_SETSIZE
. Ein typischer Fall könnte (4,4,2) von 1024 haben; Die Kernelüberprüfung (4,4,4) ist ein großer Gewinn gegenüber (1024,1024,1024), aber eine Optimierung auf (4,4,2) wäre nahezu nutzlos.nfds
, oder er muss faul sein und anrufenselect(FD_SETSIZE, ...)
, was langsamer wäre.)