Provided by: manpages-de-dev_1.11-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 früherer 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 || _XOPEN_SOURCE >= 600

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-Operationen  sind  (z. B.  Eingabe möglich). Ein Dateideskriptor gilt als bereit,
       wenn es möglich ist, eine entsprechende E/A-Operation (z.B. read (2)  ohne  zu  blockieren
       oder ein hinreichend kleines write(2)) durchzuführen.

       Das  Verhalten  von  select()  und  pselect()  ist  bis  die  folgenden  drei Unterschiede
       identisch:

       (i)    select()  verwendet  für  Zeitbegrenzungen  (timeouts)  eine  struct  timeval  (mit
              Sekunden  und  Mikrosekunden),  während  pselect() stattdessen eine 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.  Bei  den  in
       readfds  enthaltenen wird darauf geachtet, ob neue Zeichen zum Lesen ankommen (genauer: ob
       eine Leseoperation nicht blockiert; insbesondere ist ein Dateideskriptor auch am Dateiende
       (EOF) bereit). Die in writefds angegebenen werden darauf überwacht, ob Platz zum Schreiben
       verfügbar ist (ein größerer  Schreibaufruf  kann  aber  dennoch  blockieren)  und  die  in
       exceptfds  werden  auf  Ausnahmen  (exceptions) überwacht. Wenn die Funktion beendet wird,
       werden die Mengen so verändert,  dass  sie  anzeigen,  welcher  Deskriptor  seinen  Status
       geändert hat. 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 entspricht der Nummer des am höchsten nummerierten  Dateideskriptors  in  allen  drei
       Mengen, plus 1.

       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 (timeout) 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 (kein timeout), 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);

       äquivalent  zur  atomaren  (unterbrechungsfreien,  aufeinanderfolgenden)  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 ein
       globales Flag und kehrt zurück. Dann könnte eine Prüfung dieses globalen Flags 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.)

       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()  conforms to POSIX.1-2001, POSIX.1-2008, and 4.4BSD (select() first  appeared  in
       4.2BSD).  Generally  portable  to/from non-BSD systems supporting clones of the BSD socket
       layer (including System V variants). However, note that  the  System V  variant  typically
       sets the timeout variable before exit, but the BSD variant does not.

       pselect() ist in POSIX.1g und in POSIX.1-2001 und in POSIX.1-2008 definiert.

ANMERKUNGEN

       An  fd_set is a fixed size buffer. Executing FD_CLR()  or FD_SET() with a value of fd that
       is negative or is equal to or larger than FD_SETSIZE will result  in  undefined  behavior.
       Moreover, POSIX requires fd to be a valid file descriptor.

       Concerning the types involved, the classical situation is that the two fields of a timeval
       structure  are  typed  as  long  (as  shown  above),  and  the  structure  is  defined  in
       <sys/time.h>. The POSIX.1 situation is

           struct timeval {
               time_t         tv_sec;     /* Sekunden */
               suseconds_t    tv_usec;    /* Mikrosekunden */
           };

       where the structure is defined in <sys/select.h> and the data types time_t and suseconds_t
       are defined in <sys/types.h>.

       Concerning prototypes, the classical situation is that one  should  include  <time.h>  for
       select().  The  POSIX.1  situation  is that one should include <sys/select.h> for select()
       and pselect().

       Under glibc 2.0, <sys/select.h> gives the wrong prototype for pselect(). Under  glibc  2.1
       to  2.2.1,  it  gives  pselect()   when  _GNU_SOURCE  is  defined.  Since glibc 2.2.2, the
       requirements are as shown in the SYNOPSIS.

   Multithreaded applications
       If a file descriptor being monitored by select()  is closed in another thread, the  result
       is  unspecified.  On  some UNIX systems, select() unblocks and returns, with an indication
       that the file descriptor is ready (a subsequent I/O operation will  likely  fail  with  an
       error, unless another the file descriptor reopened between the time select()  returned and
       the I/O operations was performed). On Linux (and some other  systems),  closing  the  file
       descriptor  in  another thread has no effect on select(). In summary, any application that
       relies on a particular behavior in this scenario must be considered buggy.

   Unterschiede C-Bibliothek/Kernel
       The pselect()  interface described in this page is implemented by  glibc.  The  underlying
       Linux  system  call  is named pselect6(). This system call has somewhat different behavior
       from the glibc wrapper function.

       The Linux pselect6()  system call  modifies  its  timeout  argument.  However,  the  glibc
       wrapper  function  hides  this behavior by using a local variable for the timeout argument
       that is passed to the system call. Thus, the glibc pselect()  function does not modify its
       timeout argument; this is the behavior required by POSIX.1-2001.

       Das  finale Argument des Systemaufrufs pselect6() ist kein sigset_t *-Zeiger, sondern eine
       Struktur der folgenden Form:

           struct {
               const sigset_t *ss;     /* Zeiger auf Signalgruppe */
               size_t          ss_len; /* Größe (in Bytes) auf das Objekt, 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.

FEHLER

       Glibc 2.0 stellte eine Version von  pselect()  bereit,  die  das  Argument  sigmask  nicht
       akzeptierte.

       Starting  with version 2.1, glibc provided an emulation of pselect()  that was implemented
       using sigprocmask(2)  and select(). This implementation remained vulnerable  to  the  very
       race  condition  that pselect()  was designed to prevent. Modern versions of glibc use the
       (race-free)  pselect()  system call on kernels where it is provided.

       On systems that lack pselect(), reliable  (and  more  portable)  signal  trapping  can  be
       achieved using the self-pipe trick. In this technique, a signal handler writes a byte to a
       pipe whose other end is monitored by select()  in the main  program.  (To  avoid  possibly
       blocking when writing to a pipe that may be full or reading from a pipe that may be empty,
       nonblocking I/O is used when reading from and writing to the pipe.)

       Under Linux, select()  may report a socket file descriptor as "ready for  reading",  while
       nevertheless a subsequent read blocks. This could for example happen when data has arrived
       but upon examination has wrong checksum and is discarded. There may be other circumstances
       in  which  a  file descriptor is spuriously reported as ready. Thus it may be safer to use
       O_NONBLOCK on sockets that should not block.

       On Linux, select()  also modifies timeout if the call is interrupted by a  signal  handler
       (i.e.,  the  EINTR  error  return).  This is not permitted by POSIX.1. The Linux pselect()
       system call has the same behavior, but the glibc wrapper hides this behavior by internally
       copying the timeout to a local variable and passing that variable to the system call.

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  4.04  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 http://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>, Helge Kreutzmann <debian@helgefjell.de> und  Mario  Blättermann
       <mario.blaettermann@gmail.com> 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>.