focal (2) select.2.gz

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

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>.