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  ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩  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 ⟨⟩.