Provided by: manpages-fr-dev_4.21.0-2_all bug

NOM

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

BIBLIOTHÈQUE

       Bibliothèque C standard (libc, -lc)

SYNOPSIS

       #include <sys/select.h>

       typedef /* ... */ fd_set;

       int select(int nfds, fd_set *_Nullable restrict readfds,
                  fd_set *_Nullable restrict writefds,
                  fd_set *_Nullable restrict exceptfds,
                  struct timeval *_Nullable restrict 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 *_Nullable restrict readfds,
                  fd_set *_Nullable restrict writefds,
                  fd_set *_Nullable restrict exceptfds,
                  const struct timespec *_Nullable restrict timeout,
                  const sigset_t *_Nullable restrict sigmask);

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

       pselect() :
           _POSIX_C_SOURCE >= 200112L

DESCRIPTION

       Attention :  select()  ne  peut surveiller que des descripteurs de fichier dont le numéro est inférieur à
       FD_SETSIZE (1024) — une limite excessivement basse pour  beaucoup  d'applications  modernes  —  et  cette
       limite  ne  changera  pas.  Toutes  les  applications  modernes  devraient utiliser à la place poll(2) ou
       epoll(7) qui ne souffrent pas de cette limitation.

       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.

   fd_set
       Un type de structure qui peut représenter un ensemble de descripteurs de fichier. Selon POSIX, le  nombre
       maximal de descripteurs de fichier dans une structure fd_set est la valeur de la macro FD_SETSIZE.

   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.

       Important : lors de la sortie, chacun des ensembles de descripteurs de fichier est modifié sur place pour
       indiquer quels descripteurs de fichier  sont  actuellement  « prêts ».  Par  conséquent,  si  on  utilise
       select() dans une boucle, les ensembles doivent être réinitialisés avant chaque appel.

       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 la scrutation).

              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 renvoie. 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 les signaux d'abord,  traiter  les  signaux  déjà
       reçus, puis invoquer pselect() avec le sigmask désiré, en évitant la situation de concurrence.)

   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() est une structure timespec(3).

       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).Cependant, consultez BOGUES

       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é dans Linux 2.6.16. Précédemment, pselect() était émulé dans la glibc (mais voir la
       section BOGUES).

STANDARDS

       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 dans POSIX.1-2001 et POSIX.1-2008.

       fd_set est défini dans POSIX.1-2001 et suivants.

NOTES

       L'en-tête suivant fournit aussi le type fd_set : <sys/time.h>.

       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 à l'erreur ENOMEM de Linux. POSIX spécifie cette
       erreur pour poll(2) mais pas pour select(2). Des programmes portables peuvent souhaiter  vérifier  EAGAIN
       et la 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'enveloppe de la glibc.

       L'appel  système  pselect6() de Linux modifie son argument timeout. Cependant, la fonction d'enveloppe 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.

       De  la glibc 2.1 à la glibc 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).

       L'implémentation  des  paramètres  de  fd_set  en  tant  qu'arguments  valeur-résultat  est une erreur de
       conception qui est évitée dans poll(2) et 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 glibc 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 dans lesquelles le descripteur de  fichier  est  faussement  signalé  comme  prêt.
       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)
       {
           int             retval;
           fd_set          rfds;
           struct timeval  tv;

           /* 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),
       timespec(3), epoll(7), time(7)

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

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>,   Jean-Philippe   MENGUAL  <jpmengual@debian.org>  et  Jean-Pierre  Giraud  <jean-
       pierregiraud@neuf.fr>

       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.

Pages du manuel de Linux 6.03                    5 février 2023                                        select(2)