Provided by: manpages-de-dev_2.16-1_all 

BEZEICHNUNG
select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchrones E/A-Zeitmultiplexverfahren
ÜBERSICHT
/* Laut POSIX.1-2001, POSIX.1-2008 */
#include <sys/select.h>
/* Laut älterer Standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
#include <sys/select.h>
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, const struct timespec *timeout,
const sigset_t *sigmask);
Mit Glibc erforderliche Makros (siehe feature_test_macros(7)):
pselect(): _POSIX_C_SOURCE >= 200112L
BESCHREIBUNG
Mit den Funktionen select() und pselect() kann ein Programm mehrere Dateideskriptoren überwachen und
warten, bis ein oder mehrere der Dateideskriptoren »bereit« für eine Klasse von E/A-Aktionen sind (z. B.
Eingabe möglich). Ein Dateideskriptor gilt als bereit, wenn es möglich ist, eine entsprechende
E/A-Aktionen (z.B. read (2) oder ein hinreichend kleines write(2) ohne zu blockieren) durchzuführen.
select() kann nur Dateideskriptorennummern überwachen, die kleiner als FD_SETSIZE sind; poll(2) hat diese
Einschränkung nicht. Siehe FEHLER.
Das Verhalten von select() und pselect() ist bis die folgenden drei Unterschiede identisch:
(i) select() verwendet für Wartezeiten ein struct timeval (mit Sekunden und Mikrosekunden), während
pselect() stattdessen ein struct timespec (mit Sekunden und Nanosekunden) verwendet.
(ii) Während select() das Argument timeout ändern darf, um die verbleibende Zeit anzugeben, verändert
pselect() dieses Argument nicht.
(iii) Die Funktion select() hat keinen Parameter sigmask und verhält sich wie pselect, wenn ihr für
sigmask ein NULL-Zeiger übergeben wird.
Es werden drei voneinander unabhängige Mengen von Deskriptoren überwacht. Die in readfds aufgeführten
Deskriptoren werden daraufhin beobachtet, ob neue Zeichen zum Lesen ankommen (genauer: ob eine Leseaktion
nicht blockiert; insbesondere ist ein Dateideskriptor auch am Dateiende (EOF) bereit). Die
Datei-Deskriptoren in writefds werden daraufhin beobachtet, ob Platz zum Schreiben verfügbar ist (ein
größerer Schreibaufruf kann aber dennoch blockieren) und die Datei-Deskriptoren in exceptfds werden auf
außergewöhnliche Bedingungen überwacht. (Lesen Sie die Diskussion von POLLPRI in poll(2) für Beispiele
für außergewöhnliche Bedingungen.)
Wenn die Funktion beendet wird, wird jede der Datei-Deskriptorenmengen so verändert, dass sie anzeigen,
welcher Deskriptor seinen Status geändert hat. (Falls Sie daher select() innerhalb einer Schleife
verwenden, müssen die Mengen vor jedem Aufruf neu initialisiert werden.)
Jeder der drei Mengen von Deskriptoren kann als NULL angegeben werden, falls für die entsprechenden
Dateideskriptoren keine Klassen oder Ereignisse überwacht werden müssen.
Es werden vier Makros bereitgestellt, um mit diesen Mengen zu arbeiten. FD_ZERO() löscht eine Menge,
FD_SET() fügt einen Deskriptor zu einer Menge hinzu und FD_CLR() löscht diesen. FD_ISSET() prüft, ob der
Deskriptor in der Menge enthalten ist. Das ist insbesondere nach einem Aufruf von select() nützlich.
nfds sollte auf die Nummer des am höchsten nummerierten Dateideskriptors in allen drei Mengen plus 1
gesetzt werden. Der gekennzeichnete Dateideskriptor in jeder der drei Mengen wird bis zu dieser
Begrenzung geprüft (siehe aber FEHLER).
Das Argument timeout legt das Intervall fest, das select() warten sollte, bis ein Dateideskriptor bereit
wird. Der Aufruf wird blockieren, bis entweder:
* ein Dateideskriptor bereit wird,
* der Aufruf durch einen Signal-Handler unterbrochen wird, oder
* die Wartezeit abläuft.
Beachten Sie, das das Intervall timeout auf die Auflösung der Systemuhr aufgerundet wird. Durch
Verzögerungen beim Kernel-Scheduling kann dieser Wert nochmals etwas größer werden. Falls beide Felder
der Struktur timeval gleich null sind, kehrt select() sofort zurück. (Das ist praktisch für Polling).
Falls timeout gleich NULL ist (keine Wartezeit), kann select() auf unbestimmte Zeit blockieren.
sigmask ist ein Zeiger auf eine Signalmaske (siehe sigprocmask(2)); falls er ungleich NULL ist, ersetzt
pselect() zuerst die aktuelle Signalmaske mit derjenigen, auf die sigmask weist, erledigt danach die
»select«-Funktion und stellt als Letztes die ursprüngliche Signalmaske wieder her.
Abgesehen von der unterschiedlichen Genauigkeit des timeout-Arguments ist der pselect()-Aufruf
ready = pselect(nfds, &readfds, &writefds, &exceptfds,
timeout, &sigmask);
ist äquivalent zur atomaren Ausführung der folgenden Aufrufe:
sigset_t origmask;
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);
Falls man auf die Verfügbarkeit eines Signals oder eines Dateideskriptors warten möchte, ist zur
Vermeidung von Wettlaufsituationen (race conditions) eine atomare Prüfung erforderlich, die von pselect()
erledigt wird. (Angenommen, der Signal Handler setzt einen globalen Schalter und kehrt zurück. Dann
könnte eine Prüfung dieses globalen Schalters gefolgt von einem Aufruf von select() auf unbestimmte Zeit
hängen, wenn das Signal zwischen der Prüfung und vor dem Aufruf von select() eintrifft. Im Gegensatz dazu
ermöglicht es pselect() zuerst Signale zu blockieren, die eingetroffenen Signale abzuarbeiten und
anschließend pselect() mit der gewünschten sigmask aufzurufen, um Race Conditions zu vermeiden.)
Die Wartezeit (timeout)
Die Zeitstrukturen sind in <sys/time.h> als
struct timeval {
long tv_sec; /* Sekunden */
long tv_usec; /* Mikrosekunden */
};
und
struct timespec {
long tv_sec; /* Sekunden */
long tv_nsec; /* Nanosekunden */
};
definiert. (Sehen Sie sich aber weiter unten die Besonderheiten der POSIX.1-Versionen an.)
Es gibt Code, der select wie folgt aufruft: alle drei Deskriptor-Mengen leer, nfds gleich null und ein
von NULL verschiedenes timeout als recht portabler Weg, um mit Auflösungen unterhalb einer Sekunde zu
schlafen.
Unter Linux modifiziert select() timeout, um die nicht schlafend verbrachte Zeit anzuzeigen; die meisten
anderen Implementierungen tun das nicht. (POSIX.1 lässt beiderlei Verhalten zu.) Dies führt zu Problemen
sowohl bei der Portierung von Linux-Code, der timeout liest, auf andere Betriebssysteme als auch bei der
Portierung von Code nach Linux, der eine struct timeval in einer Schleife für mehrfache Aufrufe von
select() nutzt, ohne sie erneut zu initialisieren. Gehen Sie davon aus, dass timeout nach der Rückkehr
aus select() nicht definiert ist.
RÜCKGABEWERT
Bei Erfolg geben select() und pselect() die Anzahl der Datei-Deskriptoren in den drei zurückgegebenen
Deskriptor-Mengen zurück. (Das entspricht der Gesamtzahl von Bits, die in readfds, writefds und exceptfds
gesetzt sind.) Der Wert kann null sein, falls die Wartezeit abläuft, ohne das irgendetwas von Bedeutung
geschieht. Wenn ein Fehler auftritt, wird -1 zurückgegeben und errno gesetzt, um den Fehler anzugeben.
Die Datei-Deskriptor-Mengen bleiben unverändert und timeout wird undefiniert.
FEHLER
EBADF In einem der Mengen wurde ein ungültiger Dateideskriptor angegeben. (Vielleicht war es ein schon
geschlossener Dateideskriptor oder einer, bei dem ein Fehler aufgetreten ist.) Lesen Sie aber auch
FEHLER.
EINTR Ein Signal wurde abgefangen; siehe signal(7).
EINVAL nfds ist negativ oder übersteigt die Ressourcenbegrenzung RLIMIT_NOFILE (siehe getrlimit(2)).
EINVAL Der Wert von timeout ist ungültig.
ENOMEM Speicher für interne Tabellen konnte nicht bereitgestellt werden.
VERSIONEN
pselect() wurde im Linux-Kernel 2.6.16 hinzugefügt. Vorher wurde pselect() in der Glibc emuliert (siehe
aber FEHLER).
KONFORM ZU
select() erfüllt POSIX.1-2001, POSIX.1-2008 und 4.4BSD (select() erschien erstmalig in 4.2BSD). Im
Allgemeinen von/nach nicht BSD-Systeme portabel, unterstützt Klone der BSD-Socket-Schicht (einschließlich
System-V-Varianten). Beachten Sie allerdings, dass System-V-Varianten typischerweise die Variable
»timeout« vor dem Beenden setzen, die BSD-Variante aber nicht.
pselect() ist in POSIX.1g und in POSIX.1-2001 und in POSIX.1-2008 definiert.
ANMERKUNGEN
Ein fd_set ist ein Puffer fester Größe. Wird FD_CLR() oder FD_SET() mit einem Wert für fd, der negativ,
gleich groß oder größer als FD_SETSIZE ist, ausgeführt, führt dies zu nicht definiertem Verhalten.
Desweiteren verlangt POSIX, dass fd ein gültiger Dateideskriptor ist.
Das Verhalten von select() und pselect() ist von dem Schalter O_NONBLOCK nicht betroffen.
Unter einigen UNIX-Systemen kann select() mit dem Fehler EAGAIN fehlschlagen, falls es dem System nicht
gelingt, Kernel-interne Ressourcen zuzuweisen. Linux verwendet hierbei ENOMEM. POSIX legt diesen Fehler
für poll(2) aber nicht für select() fest. Portable Anwendungen könnten in einer Schleife auf EAGAIN (wie
auch auf EINTR) prüfen.
Auf Systemen, auf denen pselect() fehlt, kann ein zuverlässiges (und portableres) Abfangen von Signalen
mit dem Selbst-Pipe-Trick erreicht werden. Bei dieser Technik schreibt ein Signal-Handler ein Byte in
eine Pipe, dessen anderes Ende von select() im Hauptprogramm überwacht wird. (Um mögliches Blockieren
beim Schreiben in eine Pipe, die voll sein könnte, oder Lesen aus einer Pipe, die leer sein könnte, zu
vermeiden, wird nicht blockierende E/A beim Auslesen und Schreiben in die Pipe verwandt.)
Im Hinblick auf die beteiligten Typen ist die klassische Situation, dass zwei Felder einer Struktur
timeval vom Typ long (wie gezeigt) sind und die Struktur in <sys/time.h> definiert ist. Die
POSIX.1-Situation ist
struct timeval {
time_t tv_sec; /* Sekunden */
suseconds_t tv_usec; /* Mikrosekunden */
};
wobei die Struktur in <sys/select.h> definiert und die Datentypen time_t und suseconds_t in <sys/types.h>
definiert sind.
Im Hinblick auf Prototypen ist die klassische Situation, dass <time.h> für select() eingebunden werden
sollte. Die Situation unter POSIX.1 ist, dass <sys/select.h> für select() und pselect() eingebunden
werden sollte.
Unter Glibc 2.0 gibt <sys/select.h> den falschen Prototyp für pselect(). Unter Glibc 2.1 bis 2.2.1 gibt
er pselect(), wenn _GNU_SOURCE definiert ist. Seit Glibc 2.2.2 gelten die in ÜBERSICHT gezeigten
Anforderungen.
Korrespondenz zwischen den Benachrichtigungen select() und poll()
Innerhalb der Linux-Kernelquellen finden wir die folgende Definition, die die Korrespondenz zwischen den
lesbaren, schreibbaren und außerordentlichen Zustandsbenachrichtigungen von select() und den durch
poll(2) (und epoll(7)) bereitgestellten Ereignisbenachrichtigungen zeigt:
#define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP |
POLLERR)
/* Bereit zum Lesen */
#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
/* Bereit zum Schreiben */
#define POLLEX_SET (POLLPRI)
/* Außergewöhnliche Bedingung */
Multithreaded Anwendungen
Falls ein Dateideskriptor, der durch select() überwacht wird, in einem anderen Thread geschlossen wird,
ist das Ergebnis nicht spezifiziert. Auf einigen UNIX-Systemen entblockt select() und kehrt mit einer
Information zurück, dass der Dateideskriptor bereit ist (eine nachfolgende E/A-Aktion wird wahrscheinlich
mit einem Fehler fehlschlagen, außer ein anderer Prozess hat den Dateideskriptor zwischen dem Zeitpunkt,
zu dem select() zurückkehrte, und dem Zeitpunkt, zu der die E/A-Aktion stattfindet, wieder geöffnet).
Unter Linux (und einigen anderen Systemen) hat das Schließen des Dateideskriptors in einem anderen Thread
keinen Effekt auf select(). Zusammenfassend sollte jede Anwendung, die sich auf ein bestimmtes Verhalten
in diesem Szenario abstützt, als fehlerhaft betrachtet werden.
Unterschiede C-Bibliothek/Kernel
Der Linux-Kernel erlaubt Dateideskriptormengen beliebiger Größe und bestimmt die Größe der zu prüfenden
Mengen durch den Wert von nfds. In der Glibc-Implementierung ist der Typ fd_set allerdings von fester
Größe. Siehe auch FEHLER.
Die in dieser Seite beschriebene Schnittstelle von pselect() wird durch Glibc implementiert. Der
darunterliegende Systemaufruf heißt pselect6(). Dieser Systemaufruf hat ein etwas anderes Verhalten als
die Glibc-Wrapper-Funktion.
Der Systemaufruf pselect6() von Linux verändert das Argument timeout. Die Glibc-Wrapper-Funktion
versteckt dieses Verhalten durch Verwendung einer lokalen Variablen für das Argument »timeout«, die an
den Systemaufruf übergeben wird. Daher verändert die Glibc-Funktion pselect() nicht ihr Argument timeout;
dies ist das von POSIX.1-2001 verlangte Verhalten.
Das finale Argument des Systemaufrufs pselect6() ist kein sigset_t *-Zeiger, sondern eine Struktur der
folgenden Form:
struct {
const kernel_sigset_t *ss; /* Zeiger auf Signalgruppe */
size_t ss_len; /* Größe (in Bytes) des Objekts,
auf das durch »ss« gezeigt wird */
};
Dies erlaubt es dem Systemaufruf, sowohl einen Zeiger auf die Signalgruppe als auch seine Größe zu
ermitteln und dabei zu berücksichtigen, dass die meisten Architekturen eine maximale Anzahl von 6
Argumenten für einen Systemaufruf erlauben. Siehe sigprocmask(2) für eine Diskussion der Unterschiede
zwischen der Ansicht des Kernels und der Ansicht der Libc bezüglich der Singalmenge.
FEHLER
POSIX erlaubt einer Implementierung, eine oberer Begrenzung für den Bereich von Dateideskriptoren, die in
einer Dateideskriptorenmenge festgelegt werden können, zu definieren. Diese Begrenzung soll mittels der
Konstanten FD_SETSIZE bekannt gemacht werden. Der Linux-Kernel erzwingt keine feste Begrenzung, aber die
Glibc-Implementierung macht fd_set zu einem Typ fester Größe, wobei FD_SETSIZE als 1024 definiert ist und
die Makros FD_*() arbeiten entsprechend dieser Begrenzung. Um Dateideskriptoren größer als 1024 zu
überwachen verwenden Sie stattdessen poll(2).
Die Implementierung der Argumente fd_set als Wert-Ergebnis-Argumente bedeutet, dass sie bei jedem Aufruf
von select() neu initialisiert werden müssen. Dieser Design-Fehler wird von poll(2) vermieden, der
getrennte Strukturfelder für die Ein- und Ausgabe des Aufrufs verwendet.
Laut POSIX sollte select() alle festgelegten Dateideskriptoren in den drei Dateideskriptorenmengen bis
zur Grenze nfds-1 prüfen. Allerdings ignoriert die aktuelle Implementierung jeden Dateideskriptor in
diesen Mengen, der größer als die maximale Dateideskriptorennummer ist, die der Prozess derzeit offen
hat. Laut POSIX sollte jeder solcher Dateideskriptoren, der in einem der drei Mengen festgelegt ist, zu
einem Fehler EBADF führen.
Glibc 2.0 stellte eine Version von pselect() bereit, die das Argument sigmask nicht akzeptierte.
Beginnend mit Version 2.1 stellt Glibc eine Emulation von pselect() bereit, die mittels sigprocmask(2)
und select() implementiert wurde. Diese Implementierung blieb für den starken Ressourcenwettlauf
verwundbar, der durch das Design von pselect() vermieden werden sollte. Moderne Versionen der Glibc
verwenden den (ressourcenwettlauffreien) pselect()-Systemaufruf auf Kerneln, die ihn bereitstellen.
Unter Linux könnte select() einen Socket-Dateideskriptor als »bereit zum Lesen« melden, obwohl trotzdem
ein folgendes Lesen blockiert. Dies könnte beispielsweise passieren, wenn Daten angekommen sind, aber bei
genauerer Prüfung die falsche Prüfsumme haben und daher verworfen werden. Es mag andere Umstände geben,
in denen ein Dateideskriptor fälschlicherweise als bereit berichtet werden könnte. Daher mag es sicherer
sein, O_NONBLOCK bei Sockets zu benutzen, die nicht blockieren sollen.
Unter Linux verändert select() auch timeout falls der Aufruf durch ein Signal-Handler unterbrochen wird
(d.h. den Fehler EINTR zurückliefert). Dies wird von POSIX.1 nicht erlaubt. Der Linux-Systemaufruf
pselect() zeigt das gleiche Verhalten, aber der Glibc-Wrapper versteckt das Verhalten, indem er intern
timeout in eine lokale Variable kopiert und diese Variable an den Systemaufruf übergibt.
BEISPIEL
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Beobachte 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);
/* Verlassen Sie sich jetzt nicht auf den Wert von tv! */
if (retval == -1)
perror("select()");
else if (retval)
printf("Daten sind jetzt verfügbar.\n");
/* FD_ISSET(0, &rfds) werden wahr sein. */
else
printf("Innerhalb von fünf Sekunden keine Daten.\n");
exit(EXIT_SUCCESS);
}
SIEHE AUCH
accept(2), connect(2), poll(2), read(2), recv(2), restart_syscall(2), send(2), sigprocmask(2), write(2),
epoll(7), time(7)
Für eine Anleitung mit Diskussionen und Beispielen lesen Sie select_tut(2).
KOLOPHON
Diese Seite ist Teil der Veröffentlichung 5.03 des Projekts Linux-man-pages. Eine Beschreibung des
Projekts, Informationen, wie Fehler gemeldet werden können sowie die aktuelle Version dieser Seite finden
sich unter https://www.kernel.org/doc/man-pages/.
ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Martin Schulze <joey@infodrom.org>, Daniel Kobras
<kobras@linux.de>, Martin Eberhard Schauer <Martin.E.Schauer@gmx.de>, Mario Blättermann
<mario.blaettermann@gmail.com> und Helge Kreutzmann <debian@helgefjell.de> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer
bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an
<debian-l10n-german@lists.debian.org>.
Linux 6. März 2019 SELECT(2)