select

SELECT(2)                 Manuel du programmeur Linux                SELECT(2)



NOM
       select, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - Multiplexage
       d'entrées-sorties synchrones

SYNOPSIS
       /* D'après POSIX.1-2001 */
       #include <sys/select.h>

       /* D'après les standards précédents */
       #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);

   Exigences de macros de test de fonctionnalités pour la glibc (consultez
   feature_test_macros(7)) :

       pselect() : _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600

DESCRIPTION
       select() et pselect() permettent à un programme de surveiller
       plusieurs descripteurs de fichier, en attendant qu'au moins l'un de ces
       descripteurs soit « prêt » pour une certaine classe d'opérations
       d'entrée-sortie. Un descripteur de fichier est considéré comme prêt
       s'il est possible d'effectuer l'opération correspondante (par exemple
       read(2)) sans bloquer.

       select() et pselect() ont un comportement identique, avec trois
       différences :

       (i)    La fonction select() utilise un délai exprimé avec une struct
              timeval (secondes et microsecondes), alors que pselect() utilise
              une struct timespec (secondes et nanosecondes).

       (ii)   La fonction select() peut modifier le paramètre timeout pour
              indiquer le temps restant. La fonction pselect() ne change pas
              ce paramètre.

       (iii)  La fonction select() n'a pas de paramètre sigmask et se
              comporte comme pselect() avec une valeur NULL pour sigmask

       Il y a trois ensembles indépendants de descripteurs surveillés
       simultanément. Ceux de l'ensemble readfds seront surveillés pour
       vérifier si des caractères deviennent disponibles en lecture. Plus
       précisément, on vérifie si un appel système de lecture ne bloquera
       pas — en particulier un descripteur en fin de fichier sera considéré
       comme prêt. Les descripteurs de l'ensemble writefds seront surveillés
       pour vérifier si une écriture ne bloquera pas. Ceux de exceptfds
       seront surveillés pour l'occurrence de conditions exceptionnelles. En
       sortie, les ensembles sont modifiés pour indiquer les descripteurs qui
       ont changé d'état. Chacun des trois ensemble de descripteurs peut
       être NULL si aucun descripteur de fichier ne doit être surveillé
       pour cette classe d'événements.

       Quatre macros sont disponibles pour la manipulation des ensembles.
       FD_ZERO() efface un ensemble. FD_SET() ajoute et FD_CLR() supprime un
       descripteur dans un ensemble. FD_ISSET() vérifie si un descripteur est
       contenu dans un ensemble, principalement utile après le retour de
       select().

       nfds est le numéro du plus grand descripteur des 3 ensembles, plus 1.

       L'argument timeout précise la durée de l'intervalle pendant lequel
       select() restera bloqué dans l'attente d'un descripteur de fichier
       disponible. L'appel restera bloqué jusqu'à ce que l'un des
       événements suivants se produise :

       *  un descripteur de fichier est prêt;

       *  l'appel système a été interrompu par l'arrivée d'un signal avant
          qu'une connexion valide ne survienne ; ou bien

       *  le délai maximal expire.

       Notez que timeout est arrondi selon la granularité de l'horloge du
       système, et un retard d'ordonnancement du noyau peut entraîner un
       léger dépassement de la durée de blocage. Si les deux champs de la
       structure timeval sont nuls alors select() retourne immédiatement. (Ce
       qui sert pour des surveillances en polling). Si le timeout est NULL
       (aucune limite), select() peut bloquer indéfiniment

       sigmask est un pointeur sur un masque de signaux (consultez
       sigprocmask(2)). S'il n'est pas NULL, alors pselect() remplace d'abord
       le masque de signaux en cours par celui indiqué dans sigmask, puis
       invoque la fonction « select », et enfin restaure le masque de
       signaux à nouveau.

       Mise à part la différence de précision de l'argument timeout,
       l'appel pselect() suivant :

           ready = pselect(nfds, &readfds, &writefds, &exceptfds,
                           timeout, &sigmask);

       est équivalent à exécuter de façon atomique les appels suivants :

           sigset_t origmask;

           pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
           ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
           pthread_sigmask(SIG_SETMASK, &origmask, NULL);

       L'idée derrière pselect() est que pour l'attente d'un événement,
       que ce soit un signal ou une condition sur un descripteur, un test
       atomique est nécessaire pour éviter les situations de concurrence.
       (Supposons que le gestionnaire de signaux active un drapeau global et
       revienne. Alors un test de ce drapeau, suivi d'un appel select() peut
       bloquer indéfiniment si le signal arrive juste après le test mais
       avant l'appel. Ã l'inverse, pselect() permet de bloquer le signal
       d'abord, traiter les signaux déjà reçus, puis invoquer pselect()
       avec le sigmask, désiré, en évitant la situation de blocage.)

   Délai maximal
       Les structures temporelles concernées sont définies dans <sys/time.h>
       comme ceci :

           struct timeval {
               long    tv_sec;         /* secondes      */
               long    tv_usec;        /* microsecondes */
           };

       et

           struct timespec {
               long    tv_sec;         /* secondes     */
               long    tv_nsec;        /* nanosecondes */
           };

       (Toutefois, voir plus loin les versions POSIX.1-2001.)

       Certaines applications appellent select() avec trois ensembles de
       descripteurs vides, nfds nul, et un délai timeout non nul, afin
       d'endormir, de manière portable, le processus avec une précision plus
       fine que la seconde.

       Sous Linux, la fonction select() modifie timeout pour indiquer le temps
       restant mais la plupart des autres implémentations ne le font pas
       (POSIX.1-2001 autorise les deux comportements). Ceci pose des
       problèmes à la fois pour porter sur d'autres systèmes du code
       développé sous Linux qui utilise cette valeur de timeout modifiée,
       et pour porter sous Linux du code qui réutilise plusieurs fois la
       struct timeval sans la réinitialiser. La meilleure attitude à adopter
       est de considérer timeout comme indéfini après le retour de
       select().

VALEUR RENVOYÃE
       En cas de réussite select() et pselect() renvoient le nombre de
       descripteurs dans les trois ensembles de descripteurs renvoyés
       (c'est-à -dire le nombre total de bits à 1 dans readfds, writefds et
       exceptfds) qui peut être nul si le délai dâexpiration a été atteint
       avant que quoi que ce soit d'intéressant ne se produise. Elles
       renvoient -1 en cas dâéchec, auquel cas errno contient le code
       d'erreur ; les ensembles de descripteurs de fichier ne sont pas
       modifiés et timeout nâest plus défini.

ERREURS
       EBADF  Un descripteur de fichier invalide était dans l'un des
              ensembles. (Peut-être un descripteur déjà fermé, ou sur
              lequel une erreur s'est produite.)

       EINTR  Un signal a été intercepté ; consultez signal(7).

       EINVAL nfds est négatif ou la valeur contenue dans timeout est
              invalide.

       ENOMEM Pas assez de mémoire pour le noyau.

VERSIONS
       pselect() a été ajouté à Linux dans le noyau 2.6.16.
       Précédemment, pselect() était émulé dans la glibc (mais voir la
       section BOGUES).

CONFORMITÃ
       select() est conforme à POSIX.1-2001 et BSD 4.4 (la fonction select()
       est apparue dans BSD 4.2). Généralement portable depuis ou vers des
       systèmes non-BSD supportant des clones de la couche sockets BSD (y
       compris les variantes du System V). Néanmoins, sachez que les
       variantes du System V définissent une variable de timeout avant le
       retour alors que les variantes BSD ne le font pas.

       pselect() est défini dans POSIX.1g, et dans POSIX.1-2001.

NOTES
       Un ensemble fd_set est un tampon de taille fixe. Exécuter FD_CLR() ou
       FD_SET() avec fd négatif ou supérieur ou égal à FD_SETSIZE
       résultera en un comportement indéfini. Plus encore, POSIX demande que
       fd soit un descripteur de fichier valide.

       En ce qui concerne les types impliqués, la situation classique est que
       les deux champs de la structure timeval soient de type « long »
       (comme ci-dessus), et que la structure soit définie dans <sys/time.h>.
       La situation avec POSIX.1-2001 est

           struct timeval {
               time_t         tv_sec;     /* secondes */
               suseconds_t    tv_usec;    /* microsecondes */
           };

       avec la structure définie dans <sys/select.h> et les types de données
       time_t et suseconds_t définis dans <sys/types.h>.

       Concernant les prototypes, on demande classiquement l'inclusion de
       <time.h> pour select(). Avec POSIX.1-2001, on préfère inclure
       <sys/select.h> pour select() et pselect().

       Les bibliothèques libc4 et libc5 n'avaient pas d'en-tête
       <sys/select.h>, mais avec les glibc 2.0 et suivantes le fichier existe.
       Pour la glibc 2.0, le prototype de pselect() est toujours erroné. Avec
       la glibc 2.1 Ã  2.2.1 le prototype de pselect() est fourni si la
       constante _GNU_SOURCE est définie avant l'inclusion. Depuis la glibc
       2.2.2, les exigences sont celles indiquées dans le SYNOPSIS.

   Programmes multithreadés
       Si un descripteur de fichier surveillé par select() est fermé dans un
       autre thread, le résultat est indéterminé. Sur certains systèmes
       UNIX, select() débloque et termine, avec une indication que le
       descripteur de fichier est prêt (une opération entrée/sortie
       ultérieur risque d'échouer avec une erreur, sauf si le descripteur de
       fichier a été réouvert entre le moment où select() termine et
       l'exécution des opérations entrée/sortie). Sur Linux (et d'autres
       systèmes), la fermeture du descripteur de fichier dans un autre thread
       n'a aucun effet sur select(). En résumé, toute application qui
       s'appuie sur un comportement particulier dans ce scénario doit être
       considérée comme boguée.

   Notes sur Linux
       L'interface pselect() décrite dans cette page est implémentée par la
       glibc. L'appel système Linux sous-jacent est appelé pselect6(). Cet
       appel système a un comportement quelque peu différent de la fonction
       d'enrobage de la glibc.

       L'appel système pselect6() de Linux modifie son argument timeout.
       Cependant, la fonction d'enrobage de la glibc cache ce comportement en
       utilisant une variable locale pour l'argument timeout qui est passé Ã
       l'appel système. Par conséquent, la fonction pselect() de glibc ne
       modifie pas son paramètre timeout, ce qui est le comportement prescrit
       par POSIX.1-2001.

       Le dernier argument de l'appel système pselect6() n'est pas un
       pointeur sigset_t *, mais une structure de la forme suivante :

           struct {
               const sigset_t *ss;     /* pointeur vers l'ensemble de signaux */
               size_t          ss_len; /* taille (en octet) de l'objet pointé
                                          par 'ss' */
           };

       Cela permet à  l'appel système d'obtenir à  la fois le pointeur Ã
       l'ensemble de signaux et sa taille, tout en permettant à la plupart
       des architectures de ne prendre en charge qu'un maximum de 6 arguments
       pour un appel système.

BOGUES
       Glibc 2.0 fournissait une version de pselect() qui n'avait pas
       d'argument sigmask.

       à partir de la version 2.1, la glibc fournissait une émulation de
       pselect() implémentée avec sigprocmask(2) et select(). Cette
       implémentation était vulnérable à la condition de concurrence que
       pselect() était conçu pour éviter. Les versions récentes de la
       glibc utilisent l'appel système pselect() (sans risque de concurrence)
       si le noyau le fournit.

       Sur les systèmes sans pselect, une gestion plus sûre (et plus
       portable) des signaux peut être obtenue en utilisant un tube : un
       gestionnaire de signal écrit un octet dans un tube dont select() dans
       le programme principal surveille l'autre extrémité. (Pour éviter la
       possibilité de blocage lors de l'écriture dans un tube peut-être
       plein, ou la lecture dans un tube peut-être vide, des entrées et
       sorties non bloquantes sont utilisées pour la lecture et l'écriture
       dans le tube.)

       Sous Linux, select() peut signaler un descripteur de fichier socket
       comme « prêt à lire » alors qu'une lecture suivante bloque. Cela
       peut, par exemple, survenir lorsque des données sont arrivées mais,
       après vérification, ont une mauvaise somme de contrôle et sont
       rejetées. Cela peut également arriver dans d'autres circonstances.
       Aussi, il est plus sûr d'utiliser O_NONBLOCK sur des sockets qui ne
       devraient pas bloquer.

       Sous Linux, select() modifie également timeout si l'appel est
       interrompu par un gestionnaire de signaux (code d'erreur EINTR). Ceci
       est interdit par POSIX.1-2001. L'appel système pselect() de Linux se
       comporte de la même façon, mais la glibc cache cette particularité
       en copiant timeout vers une variable locale, et en passant cette
       variable à l'appel système.

EXEMPLE
       #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;

           /* Surveiller stdin (fd 0) en attente d'entrées */
           FD_ZERO(&rfds);
           FD_SET(0, &rfds);

           /* Attends jusqu'Ã  5 secondes. */
           tv.tv_sec = 5;
           tv.tv_usec = 0;

           retval = select(1, &rfds, NULL, NULL, &tv);
           /* Considérer tv comme indéfini maintenant ! */

           if (retval == -1)
               perror("select()");
           else if (retval)
               printf("Des données sont disponibles maintenant\n");
               /* FD_ISSET(0, &rfds) est alors vrai. */
           else
               printf("Aucune donnée durant les cinq secondes.\n");

           exit(EXIT_SUCCESS);
       }

VOIR AUSSI
       accept(2), connect(2), poll(2), read(2), recv(2), send(2),
       sigprocmask(2), write(2), epoll(7), time(7)

       Pour un tutoriel avec des exemples, consultez select_tut(2).

COLOPHON
       Cette page fait partie de la publication 3.70 du projet man-pages
       Linux. Une description du projet et des instructions pour signaler des
       anomalies peuvent être trouvées à l'adresse
       http://www.kernel.org/doc/man-pages/.

TRADUCTION
       Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a
       <http://po4a.alioth.debian.org/> par l'équipe de traduction
       francophone au sein du projet perkamon
       <http://perkamon.alioth.debian.org/>.

       Christophe Blaess <http://www.blaess.fr/christophe/> (1996-2003), Alain
       Portal <http://manpagesfr.free.fr/> (2003-2006).  Julien Cristau et
       l'équipe francophone de traduction de Debian (2006-2009).

       Veuillez signaler toute erreur de traduction en écrivant Ã
       <perkamon-fr@traduc.org>.

       Vous pouvez toujours avoir accès à la version anglaise de ce document
       en utilisant la commande « LC_ALL=C man <section> <page_de_man> ».



Linux                           31 janvier 2014                      SELECT(2)