Provided by: manpages-fr-dev_3.65d1p1-1_all bug

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.65 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     à
       <debian-l10n-french@lists.debian.org>   ou   par   un  rapport  de  bogue  sur  le  paquet
       manpages-fr.

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