Provided by: manpages-fr-dev_4.13-4_all bug

NOM

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

SYNOPSIS

       #include <sys/select.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);

       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 (consulter feature_test_macros(7)) :

       pselect(): _POSIX_C_SOURCE >= 200112L

DESCRIPTION

       select()  permet à 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 (par exemple
       une entrée est possible).  Un  descripteur  de  fichier  est  considéré  comme  prêt  s'il  est  possible
       d'effectuer l'opération correspondante (par exemple read(2) ou un write(2) assez petit) sans bloquer.

       select()  ne peut surveiller que des numéros de descripteurs de fichier inférieurs à FD_SETSIZE ; poll(2)
       et epoll(7) n'ont pas cette limitation. Voir les BOGUES.

   Ensembles de descripteurs de fichier
       Les paramètres principaux de select() sont trois « ensembles » de descripteurs de fichier (déclarés  avec
       le  type  fd_set),  qui  permettent  à l'appelant d'attendre trois classes d'événements sur l'ensemble de
       descripteurs de fichier indiqué. Chacun des paramètres de fd_set peut être indiqué comme  NULL  si  aucun
       descripteur de fichier ne doit être surveillé pour la classe d'événements correspondante.

       Notez  bien :  lors  du renvoi, chacun des ensembles de descripteurs de fichier est modifié pour indiquer
       les descripteurs actuellement « prêts ». Ainsi, si  on  utilise  select()  dans  une  boucle,  alors  les
       ensembles  doivent  être réinitialisés avant chaque appel. L'implémentation des paramètres fd_set en tant
       que paramètres valeur-résultats est une erreur de conception évitée dans poll(2) et epoll(7).

       Le contenu d'un ensemble  de  descripteurs  de  fichier  peut  être  manipulé  en  utilisant  les  macros
       suivantes :

       FD_ZERO()
              Cette  macro  efface  (supprime  tous les descripteurs de fichier) set. Elle doit être utilisée en
              tant que première étape de l'initialisation d'un ensemble de descripteurs de fichier.

       FD_SET()
              Cette macro ajoute le descripteur de fichier fd à set. L'ajout d'un descripteur  de  fichier  déjà
              présent dans l'ensemble est sans effet et ne produit pas d'erreur.

       FD_CLR()
              Cette  macro  supprime  le  descripteur  de  fichier fd de set. La suppression d'un descripteur de
              fichier non présent dans l'ensemble est sans effet et ne produit pas d'erreur.

       FD_ISSET()
              select() modifie le contenu des ensembles en fonction des règles  décrites  ci-dessous.  Après  un
              appel  à select(), la macro FD_ISSET() peut être utilisée pour tester si un descripteur de fichier
              est présent dans un ensemble. FD_ISSET() ne renvoie pas zéro si le descripteur de fichier  fd  est
              présent dans set, sinon il le renvoie.

   Arguments
       Les paramètres de select() sont les suivants :

       readfds
              Les descripteurs de fichier de cet ensemble sont surveillés pour voir s'ils sont prêts en lecture.
              Un  descripteur  de fichier est prêt si une opération de lecture ne bloquera pas ; en particulier,
              le descripteur de fichier est prêt sur une fin-de-fichier.

              Après que select() ait renvoyé, readfds sera vidé de tous les descripteurs de  fichier  sauf  ceux
              prêts en lecture.

       writefds
              Les  descripteurs  de  fichier  de  cet  ensemble  sont  surveillés  pour voir s'ils sont prêts en
              écriture. Un descripteur de fichier  est  prêt  si  une  opération  d'écriture  ne  bloquera  pas.
              Cependant,  même  si  un  descripteur  de  fichier  est  indiqué  comme inscriptible, une écriture
              abondante peut toujours bloquer.

              Après que select() ait renvoyé, writefds() sera vidé de tous les  descripteurs  de  fichier,  sauf
              ceux prêts en écriture.

       exceptfds
              Les   descripteurs   de   fichier   de  cet  ensemble  sont  surveillés  en  cas  de  « conditions
              exceptionnelles ». Pour des exemples de conditions exceptionnelles, voir le point sur POLLPRI dans
              poll(2).

              Après que select() ait renvoyé, exceptfds() sera vidé de tous les descripteurs  de  fichier,  sauf
              ceux où s'est produite une condition exceptionnelle.

       nfds   Ce  paramètre  doit  être  positionné sur le numéro du plus grand descripteur des trois ensembles,
              plus 1. Les descripteurs de fichier indiqués dans chaque ensemble sont vérifiés dans cette  limite
              (mais voir BOGUES).

       timeout
              L'argument  timeout  est  une  structure  timeval  (décrite  ci-dessous)  qui  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'à :

                •
                un descripteur de fichier devient prêt ;

                •
                l’appel est interrompu par un gestionnaire de signal ;

                •
                le délai expire.

              Notez  que  l'intervalle  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 valent  zéro,  select()  renvoie  immédiatement  (c'est
              utile pour du sondage).

              Si  timeout  est indiqué comme étant NULL, select() restera bloqué dans l'attente d'un descripteur
              de fichier disponible :

   pselect()
       L'appel système pselect() permet à une application d'attendre de manière sécurisée  un  signal  ou  qu'un
       descripteur de fichier soit prêt.

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

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

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

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

       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 (si sigmask est NULL, le masque  de
       signaux n'est pas modifié pendant l'appel pselect()).

       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);

       La raison de la présence de 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
       Le paramètre timeout de select() est une structure du type suivant :

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

       Le paramètre correspondant à pselect() a le type suivant :

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

       Sous Linux, la fonction select() modifie timeout pour indiquer le temps  non  endormi ;  la  plupart  des
       autres  implémentations ne le font pas (POSIX.1 autorise les deux comportements). Cela 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 pour
       plusieurs select()s dans une boucle 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 définis dans readfds, writefds et  exceptfds)
       qui peut être nul si le délai d’expiration a été atteint avant qu'un descripteur de fichier ne soit prêt.

       En  cas  d'erreur, la valeur de retour est -1 et errno est définie pour préciser l'erreur ; les ensembles
       de descripteurs de fichiers ne sont pas modifiés et timeout devient indéfini.

ERREURS

       EBADF  Un descripteur de fichier non valable é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 dépasse la limite de ressource RLIMIT_NOFILE (voir getrlimit(2)).

       EINVAL La valeur contenue dans timeout n'est pas valable.

       ENOMEM Incapacité d'allouer de la mémoire pour des tables internes.

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,  POSIX.1-2008  et 4.4BSD (la fonction select() est apparue dans
       4.2BSD). Généralement portable depuis ou vers des systèmes non BSD gérant des clones de la couche sockets
       BSD (y compris les variantes de System V). Néanmoins, sachez que les variantes de System V définissent la
       variable timeout avant le retour alors que les variantes BSD ne le font pas.

       pselect() est défini dans POSIX.1g ainsi que POSIX.1-2001 et POSIX.1-2008.

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

       Les opérations select() et pselect() ne sont pas concernées par l'attribut O_NONBLOCK.

       Sur d'autres systèmes UNIX, select() peut échouer avec l'erreur EAGAIN si le système ne  parvient  pas  à
       allouer  des  ressources  internes du noyau contrairement au ENOMEM de Linux. POSIX spécifie cette erreur
       pour poll(2) mais pas pour select(2). Des programmes  portables  peuvent  souhaiter  vérifier  EAGAIN  en
       boucle comme avec EINTR.

   L'astuce du « self-pipe »
       Sur  les systèmes sans pselect, une gestion plus sûre (et plus portable) des signaux peut être obtenue en
       utilisant l'astuce du « self-pipe » : 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 pouvant être plein ou de la lecture dans un tube pouvant être vide, des entrées
       et sorties non bloquantes sont utilisées pour la lecture et l'écriture dans le tube.)

   Émuler usleep(3)
       Avant l'arrivée de  usleep(3),  certaines  applications  appelaient  select()  avec  trois  ensembles  de
       descripteurs  vides,  nfds  nul  et  un  délai timeout non NULL, afin d'endormir, de manière portable, le
       processus avec une précision plus fine que la seconde.

   Correspondance entre les notifications de select() et de poll()
       Dans les sources du noyau Linux, nous trouvons les définitions suivantes qui montrent  la  correspondance
       entre  les  notifications  de lisibilité, d'inscriptibilité et de condition exceptionnelle de select() et
       les notifications d'événements fournies par poll(2) et epoll(7) :

           #define POLLIN_SET  (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN |
                                EPOLLHUP | EPOLLERR)
                              /* Prêt en lecture */
           #define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT |
                                EPOLLERR)
                              /* Prêt en écriture */
           #define POLLEX_SET  (EPOLLPRI)
                              /* Condition exceptionnelle */

   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érieure 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.

   différences entre bibliothèque C et noyau
       Le  noyau  Linux  autorise  les  ensembles  de  descripteurs  de  fichier  de n'importe quelle taille, en
       déterminant la taille des  ensembles  à  vérifier  à  partir  de  la  valeur  de  nfds.  Cependant,  dans
       l'implémentation de la glibc, le type fd_set a une taille fixe. Voir aussi les BOGUES.

       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 la 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 kernel_sigset_t *ss;   /* Pointeur vers un ensemble de signaux */
               size_t ss_len;               /* Taille (en octets) de l'objet vers
                                               lequel pointe 'ss' */
           };

       Cela  permet  à  l'appel système d'obtenir à la fois le pointeur vers 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. Voir sigprocmask(2) pour un point sur la différence entre la vision du noyau et
       celle de la libc de l'ensemble de signaux.

   Détails historiques sur la glibc
       La glibc 2.0 fournissait une mauvaise version de pselect() qui n'avait pas d'argument sigmask.

       Dans les versions de la glibc 2.1 à 2.2.1, on peut définir _GNU_SOURCE afin d'obtenir la  déclaration  de
       pselect() depuis <sys/select.h>.

BOGUES

       POSIX  autorise  une  implémentation  à  définir  une limite supérieure indiquée à l'aide de la constante
       FD_SETSIZE, dans l'intervalle de descripteurs de fichier qui peuvent être indiqués dans  un  ensemble  de
       descripteurs  de  fichier.  Le  noyau Linux n'impose pas de limite fixe mais l'implémentation de la glibc
       fait que fd_set est un type de taille fixe, où FD_SETSIZE est défini à  1024  et  où  les  macros  FD_*()
       agissent  en  fonction  de  cette  limite. Pour surveiller des descripteurs de fichier supérieurs à 1023,
       utilisez plutôt poll(2) ou epoll(7).

       Selon POSIX, select() devrait vérifier tous les descripteurs  de  fichier  des  trois  ensembles  jusqu'à
       nfds-1.  Cependant,  l'implémentation  actuelle  ignore  tout  descripteur  de fichier dans ces ensembles
       supérieur au numéro le plus élevé de descripteur de fichier que le processus a ouvert.  Selon  POSIX,  un
       tel descripteur de fichier indiqué dans l'un des ensembles devrait provoquer une erreur EBADF.

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

       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). Cela est interdit par POSIX.1. 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.

EXEMPLES

       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/select.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);

           /* Attendre jusqu'à 5 secondes. */

           tv.tv_sec = 5;
           tv.tv_usec = 0;

           retval = select(1, &rfds, NULL, NULL, &tv);
           /* Ne pas s'appuyer sur la valeur de tv 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), restart_syscall(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 5.10 du projet man-pages Linux. Une description du projet et des
       instructions  pour  signaler  des  anomalies et la dernière version de cette page peuvent être trouvées à
       l'adresse https://www.kernel.org/doc/man-pages/.

TRADUCTION

       La  traduction  française   de   cette   page   de   manuel   a   été   créée   par   Christophe   Blaess
       <https://www.blaess.fr/christophe/>,   Stéphan   Rafin   <stephan.rafin@laposte.net>,   Thierry   Vignaud
       <tvignaud@mandriva.com>, François Micaux, Alain Portal  <aportal@univ-montp2.fr>,  Jean-Philippe  Guérard
       <fevrier@tigreraye.org>,   Jean-Luc   Coulon   (f5ibh)   <jean-luc.coulon@wanadoo.fr>,   Julien   Cristau
       <jcristau@debian.org>,     Thomas     Huriaux      <thomas.huriaux@gmail.com>,      Nicolas      François
       <nicolas.francois@centraliens.net>,     Florentin     Duneau    <fduneau@gmail.com>,    Simon    Paillard
       <simon.paillard@resel.enst-bretagne.fr>,    Denis    Barbier    <barbier@debian.org>,    David     Prévot
       <david@tilapin.org>,     Cédric     Boutillier     <cedric.boutillier@gmail.com>,    Frédéric    Hantrais
       <fhantrais@gmail.com> et Jean-Philippe MENGUAL <jpmengual@debian.org>

       Cette traduction est une documentation libre ; veuillez vous  reporter  à  la  GNU General Public License
       version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si  vous  découvrez  un  bogue  dans la traduction de cette page de manuel, veuillez envoyer un message à
       debian-l10n-french@lists.debian.org.

Linux                                            1 novembre 2020                                       SELECT(2)