SELECT(2)

BEZEICHNUNG
select - Synchrone I/O-Multiplexsteuerung

ÜBERSICHT
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int select(int n, fd_set *readfds, fd_set * writefds, fd_set *exceptfds, struct timeval timeout);

FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);

BESCHREIBUNG
select() wartet für eine Reihe von Dateideskriptoren, daß sich deren Status ändert. Es werden drei voneinander unabhängige Mengen von Deskriptoren behandelt. Bei den in readfds enthaltenen wird darauf geachtet, daß neue Zeichen zum Lesen ankommen, bei den in writefds angegebenen wird reagiert, wenn weitere Zeichen geschrieben werden können, und bei den in exceptfds angegebenen Deskriptoren wird reagiert, wenn etwas außergewöhnliches passiert ist. Wenn die Routine beendet wird, werden die übergebenen Mengen so verändert, daß sie anzeigen, welcher Deskriptor seinen Status geändert hat. Vier Makros werden bereitgestellt, um mit diesen Mengen zu arbeiten. FD_ZERO löscht eine Menge, FD_SET und FD_CLR fügt einen Deskriptor zur Menge hinzu bzw. löscht diesen, FD_ISSET prüft, ob der Deskriptor in der Menge enthalten ist. Dieses ist insbesondere nach einem select()-Aufruf sinnvoll. n entspricht der Zahl des am höchsten nummerierten Datei-Deskriptors in allen drei Mengen, plus 1. timeout ist eine obere zeitliche Grenze, die select() wartet, bis es weitergeht. Ist der Wert null, kehrt select() sofort zurück. Wenn timeout NULL ist (kein timeout), kann select() unendlich lang blockieren.

RÜCKGABEWERTE
Bei Erfolg gibt select() die Anzahl der Deskriptoren zurück, deren Status sich geändert hat. Wenn ein Fehler aufgetreten ist, wird -1 zurückgegeben und errno entsprechend gesetzt. Die Mengen und timeout befinden sich in einem undefinierten Zustand, auf deren Inhalt sollte sich also bei einem Fehler nicht mehr verlassen werden.

FEHLER

EBADF
    In einer der Mengen wurde ein ungültiger Datei-Deskriptor angegeben.

EINTR
    Ein nicht-blockierendes Signal wurde empfangen.

EINVAL
    n ist negativ.

ENOMEM
    select() ist nicht in der Lage, Speicher für die internen Tabellen zu bekommen.

ANMERKUNGEN
Einige Programme rufen select() mit drei leeren Mengen, n gleich null und einem von null verschiedenen timeout auf, um eine portable Möglichkeit zu haben, ein sleep() mit der Präzision von Bruchteilen einer Sekunde zu benutzen. Bei Linux wird timeout derart verändert, daß es der nicht verstrichenen Zeit entspricht (relativ zum vorherigen timeout). Die meisten anderen Implementierungen unterlassen dieses, was Probleme mit sich bringt, wenn unter Linux geschriebener Quellcode, der timeout auswertet, auf andere Betriebssysteme portiert wird, und wenn Quellcode von anderen Betriebssystemen auf Linux portiert wird, der das struct timeval für mehrere select()s in einer Schleife ohne Reinitialisierung verwendet. Portabler Code sollte daher annehmen, daß timeout undefiniert ist, nachdem select() beendet ist. Nachdem der einzige Schreiber eine named Pipe schließt, wird select() zurückkehren und angeben, daß etwas von der Pipe gelesen werden kann. Wenn dann von dieser gelesen wird, wird read(2) 0 zurückliefern, was das Dateiende markiert. Code, der annimmt, daß select() blockiert, sollte die Pipe mit O_RDWR statt O_RDONLY öffnen.

BEISPIEL
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    fd_set rfds;
    struct timeval tv;
    int retval;
    /* Achte auf 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);
    /* Verlaß Dich jetzt bloß nicht auf den Wert von tv! */
    if (retval)
        printf("Daten sind jetzt da.\n");
        /* FD_ISSET(0, &rfds) müßte jetzt true sein. */
    else
        printf("Keine Datein innerhalb von fünf Sekunden.\n");
    exit(0);
}

SIEHE AUCH
accept(2), connect(2), read(2), recv(2), send(2), write(2).