Provided by: manpages-fr-dev_4.26.0-1_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.

   Argument
       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

       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.

STANDARDS

       POSIX.1-2008.

HISTORIQUE

       select()
              POSIX.1-2001, 4.4BSD (apparu 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).  Sachez néanmoins, que les variantes de System V
              définissent la variable timeout avant le retour alors que les variantes BSD ne le font pas.

       pselect()
              Linux 2.6.16. POSIX.1g, POSIX.1-2001.

              Précédemment, il était émulé dans la glibc (mais voir la section BOGUES).

       fd_set POSIX.1-2001.

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.

   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.9.1                    15 juin 2024                                         select(2)