Provided by: manpages-de-dev_1.11-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 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>.
Linux 23. Juli 2015 SELECT(2)