select

SELECT(2)                  Linux-Programmierhandbuch                 SELECT(2)



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)