Provided by: manpages-fr-dev_4.23.1-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  ⟨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⟩.