Provided by: manpages-fr-dev_3.07.1-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  (voir
   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é  de  statut. 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()  et  FD_CLR()  ajoutent   et
       suppriment  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.

       timeout  est  une  limite supérieure au temps passé dans select() avant
       son retour. 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 (voir 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;

           sigprocmask(SIG_SETMASK, &sigmask, &origmask);
           ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
           sigprocmask(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   retournés
       (c’est-à-dire  le  nombre  total  de  bits  à 1 dans readfds, writefds,
       exceptfds) qui peut être nul si le délai de timeout a expiré avant  que
       quoi  que ce soit d’intéressant ne se produise. Ils retournent -1 s’ils
       échouent, auquel cas errno contient le code d’erreur ; les ensembles et
       timeout  ne  sont  plus définis, ne vous fiez plus à leur contenu après
       une erreur.

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é ; voir 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 fixent 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.   Avec   glibc  2.2.2-2.2.4,  il  faut  que  la  constante
       _XOPEN_SOURCE soit définie avec une valeur supérieure ou égale  à  600.
       Quoiqu’il  en  soit, depuis POSIX.1-2001, le bon prototype devrait être
       défini par défaut.

   Notes sur Linux
       L’appel système  pselect()  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 argument timeout, ce qui est le  comportement  prescrit
       par POSIX.1-2001.

BOGUES

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

       Depuis la version 2.1, la glibc  fournit  une  émulation  de  pselect()
       implémentée  avec  sigprocmask(2) et select(). Cette implémentation est
       vulnérable à la condition de concurrence que pselect() est  conçu  pour
       éviter.  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é).

       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

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

       D’autres pages ayant un vague rapport : accept(2), connect(2), poll(2),
       read(2), recv(2), send(2), sigprocmask(2), write(2), epoll(7), time(7)

COLOPHON

       Cette page fait partie de  la  publication  3.07  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

       Cette  page  de  manuel  a  été  traduite et mise à jour par Christophe
       Blaess <http://www.blaess.fr/christophe/> entre 1996 et 2003, puis  par
       Alain  Portal  <aportal AT univ-montp2 DOT fr> jusqu’en 2006, et mise à
       disposition sur http://manpagesfr.free.fr/.

       Les mises à jour et corrections de la version présente dans Debian sont
       directement gérées par Julien Cristau <jcristau@debian.org> et l’équipe
       francophone de traduction de Debian.

       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> ».