Provided by:
manpages-de-dev_0.5-2_all 
BEZEICHNUNG
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - Synchrone I/O-Mul‐
tiplexsteuerung
BERSICHT
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout);
int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set
*exceptfds, const struct timespec *timeout, sigset_t *sigmask);
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
BESCHREIBUNG
Die Funktionen select und pselect überwachen den Dateistatus für eine
Reihe von Datei-Deskriptoren.
Die Funktionsweise der beiden Varianten ist identisch, abgesehen von
drei Unterschieden:
(i) The select-Funktion verwendet zur Angabe von Zeitlimits eine
Struktur vom Typ struct timeval (mit Sekunden und Mikrosekun‐
den), pselect hingegen den Typ struct timespec (mit Sekunden und
Nanosekunden). Die Strukturen sind über /usr/include/sys/time.h
definiert als:
struct timeval {
long tv_sec; /* Sekunden */
long tv_usec; /* Mikrosekunden */
};
und
struct timespec {
long tv_sec; /* Sekunden */
long tv_nsec; /* Nanosekunden */
};
(ii) Während select den Parameter timeout mitunter verändert, um
anzuzeigen, wie viel Zeit des Limits noch verblieben ist, lässt
pselect den Wert immer unverändert.
(iii) Die select-Funktion besitzt keinen sigmask-Parameter und verhält
sich wie pselect, das mit einer sigmask von NULL aufgerufen
wurde.
Es werden drei voneinander unabhängige Mengen von Deskriptoren behan‐
delt. Bei den in readfds enthaltenen wird darauf geachtet, ob neue
Zeichen zum Lesen ankommen. (Genauer, es wird kontrolliert, ob ein
nachfolgender read-Systemaufruf sofort zurückkehren würde. Diese
Bedingung ist insbesondere auch dann erfüllt, wenn der Deskriptor auf
das Dateiende verweist.) Bei den in writefds angegebenen Deskriptoren
wird reagiert, wenn weitere Zeichen geschrieben werden können, und bei
den in exceptfds angegebenen Deskriptoren, wenn etwas außergewöhnliches
passiert ist. Kehrt der Systemaufruf zurück, sind die übergebenen
Mengen so verändert, dass sie anzeigen, welcher Deskriptor seinen Sta‐
tus geändert hat.
Vier Makros stehen bereit, um mit diesen Mengen zu arbeiten. FD_ZERO
löscht eine Menge, FD_SET und FD_CLR fügen einen Deskriptor zur Menge
hinzu bzw. löschen diesen, FD_ISSET prüft, ob der Deskriptor in der
Menge enthalten ist. Das ist insbesondere nach einem select- oder pse
lect-Aufruf sinnvoll.
n entspricht der Zahl des am höchsten nummerierten Datei-Deskriptors in
allen drei Mengen, plus 1.
timeout gibt ein Zeitlimit an, das select und pselect maximal verstre‐
ichen lassen, bevor sie zurückkehren. Ist das Zeitlimit null, so
kehren die Funktionen sofort zurück. Besitzt timeout selbst den Wert
NULL, so wird kein Limit gesetzt, und die Funktionen können unendlich
lange blockieren.
sigmask ist entweder NULL oder ein Zeiger auf eine Signalmaske wie in
sigprocmask(2) beschrieben. Im zweiten Fall ersetzt pselect die
aktuelle Signalmaske durch sigmask, führt dann den select-Aufruf aus
und stellt anschließend die ursprüngliche Maske wieder her.
Die Idee hinter pselect geht zurück auf folgende Situation: Ein Pro‐
gramm wartet gleichzeitig auf ein Signal oder eine Veränderung an einem
Datei-Deskriptor. Trifft das Signal ein, so setzt der Signalhandler
eine globale Variable. Im Hauptprogramm wird zunächst getestet, ob die
Variable gesetzt ist und andernfalls ein select-Aufruf gestartet.
Trifft das Signal zwischen dem Test und dem select-Aufruf ein, so kann
das dazu führen, dass das Programm nicht mehr beendet wird. pselect
hingegen erlaubt es, diese so genannte Race Condition zu umgehen, indem
das Signal zunächst geblockt, getestet und erst unmittelbar mit dem
select-Aufruf wieder freigegeben wird. Da der Linux-Kernel bislang
keinen speziellen pselect-Systemaufruf bereit stellt, muss die aktuelle
glibc2 ihn durch mehrere Aufrufe emulieren. Die Fehlerquelle ist daher
auch mit pselect nach wie vor vorhanden.
R CKGABEWERTE
Bei Erfolg geben select und pselect die Anzahl der Deskriptoren zurück,
deren Status sich geändert hat. Der Rückgabewert kann auch null sein,
wenn das Zeitlimit erreicht wurde, bevor etwas interessantes passiert
ist. Wenn ein Fehler aufgetreten ist, wird -1 zurückgegeben und errno
entsprechend gesetzt. Die Mengen und timeout befinden sich dann in
einem undefinierten Zustand. Auf ihren Inhalt sollte man sich folglich
bei einem Fehler nicht mehr verlassen.
FEHLER
EBADF In einer der Mengen wurde ein ungültiger Datei-Deskriptor
angegeben.
EINTR Ein nicht-blockiertes Signal wurde empfangen.
EINVAL n ist negativ.
ENOMEM select war nicht in der Lage, Speicher für die internen
Tabellen zu bekommen.
ANMERKUNGEN
Einige Programme rufen select mit drei leeren Mengen, n gleich null und
einem von null verschiedenen timeout auf, um eine portable Möglichkeit
zu haben, ein sleep mit der Präzision von Bruchteilen einer Sekunde zu
benutzen.
Bei Linux wird timeout derart verändert, dass es dem noch nicht ver‐
strichenen Teil des Zeitlimits entspricht. Die meisten Implementierun‐
gen anderer Betriebssysteme unterlassen dies. Das bringt Probleme mit
sich, wenn unter Linux geschriebener Quellcode, der timeout auswertet,
auf andere Betriebssysteme portiert wird, und wenn Quellcode von
anderen Betriebssystemen auf Linux portiert wird, der das struct
timeval für mehrere selects in einer Schleife verwendet, ohne ihn
jedesmal neu zu initialisieren. Portabler Code sollte daher annehmen,
dass timeout undefiniert ist, nachdem select beendet wurde.
Wenn der einzige Schreiber eine Named-Pipe geschlossen hat, kehrt
select zurück und signalisiert, dass etwas von der Pipe gelesen werden
kann. Ein anschließender read-Aufruf liefert jedoch null zurück, da
das Dateiende erreicht ist. Code, der annimmt, dass select in diesem
Fall blockiert, sollte die Pipe mit O_RDWR statt O_RDONLY öffnen.
BEISPIEL
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Achte auf stdin (fd 0), um zu sehen, wenn es
* Eingaben gibt.
*/
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Warte bis zu fünf Sekunden. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Verlaß Dich jetzt bloß nicht auf den Wert von tv! */
if (retval)
printf("Daten sind jetzt da.\n");
/* FD_ISSET(0, &rfds) müsste jetzt true sein. */
else
printf("Keine Dateien innerhalb von fünf Sekunden.\n");
exit(0);
}
4.4BSD. (Die select-Funktion trat das erste Mal in 4.2BSD auf.)
Gewöhnlich auch portierbar auf Nicht-BSD-Systeme (System V-Varianten
eingeschlossen), die eine Schnittstelle vom Typ des BSD-Socketlayers
unterstützen. Zu beachten ist jedoch, dass die System V-Varianten typ‐
ischerweise die timeout-Variable vor der Rückkehr setzen. Bei den BSD-
Varianten ist das nicht üblich.
Die pselect-Funktion ist in IEEE Std 1003.1g-2000 (POSIX.1g) definiert.
Sie ist seit glibc2.1 implementiert. Auch glibc2.0 besitzt eine Funk‐
tion dieses Namens, die jedoch keinen Parameter sigmask verwendet.
accept(2), connect(2), poll(2), read(2), recv(2), send(2), sigproc
mask(2), write(2).