dwww Home | Manual pages | Find package

select(2)                     System Calls Manual                    select(2)

NOM
       select,  pselect,  FD_CLR,  FD_ISSET,  FD_SET, FD_ZERO, fd_set - Multi-
       plexage 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  excessi-
       vement 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  consi-
       déré  comme  prêt  s'il est possible d'effectuer l'opération correspon-
       dante (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  des-
       cripteurs  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 des-
       cripteurs de fichier indiqué. Chacun des paramètres de fd_set peut être
       indiqué comme NULL si aucun descripteur de fichier ne  doit  être  sur-
       veillé 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  fi-
       chier  sont  actuellement  « prêts ». Par conséquent, si on utilise se-
       lect() 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'en-
              semble 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_IS-
              SET() peut être utilisée pour tester si un  descripteur  de  fi-
              chier  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 particu-
              lier, 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  inscrip-
              tible, 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 fi-
              chier indiqués dans chaque ensemble sont vérifiés dans cette li-
              mite (mais voir BOGUES).

       timeout
              L'argument timeout est une structure  timeval  (décrite  ci-des-
              sous)  qui  précise  la durée de l'intervalle pendant lequel se-
              lect() 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 ma-
       niè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 time-
          val (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 indi-
          quer le temps restant. La fonction pselect() ne change  pas  ce  pa-
          ramè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  sigproc-
       mask(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 à nou-
       veau (si sigmask est NULL, le masque de signaux n'est pas modifié  pen-
       dant 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 (PO-
       SIX.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 se-
       lect()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 se-
       lect().

VALEUR RENVOYÉE
       En cas de réussite select() et pselect() renvoient le  nombre  de  des-
       cripteurs   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  en-
              sembles  (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  fonc-
       tion 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 PO-
       SIX.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'at-
       tribut 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 se-
       lect() 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  sui-
       vantes  qui montrent la correspondance entre les notifications de lisi-
       bilité, 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éra-
       tions 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  se-
       lect().  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éri-
       fier à 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 ap-
       pel  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.  Ce-
       pendant,  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 indi-
       quée à l'aide de la constante FD_SETSIZE, dans l'intervalle de descrip-
       teurs de fichier qui peuvent être indiqués dans un ensemble de descrip-
       teurs de fichier. Le noyau Linux n'impose pas de limite fixe mais l'im-
       plé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 fonc-
       tion 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 va-
       leur-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  ac-
       tuelle  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  pse-
       lect()  implémentée  avec sigprocmask(2) et select(). Cette implémenta-
       tion é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 inter-
       rompu 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  ti-
       meout  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 Chris-
       tophe Blaess <https://www.blaess.fr/christophe/>, Stéphan  Rafin  <ste-
       phan.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.cou-
       lon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>,  Thomas  Huriaux
       <thomas.huriaux@gmail.com>,  Nicolas François <nicolas.francois@centra-
       liens.net>, Florentin Duneau <fduneau@gmail.com>, Simon  Paillard  <si-
       mon.paillard@resel.enst-bretagne.fr>,    Denis   Barbier   <barbier@de-
       bian.org>, David Prévot  <david@tilapin.org>,  Cédric  Boutillier  <ce-
       dric.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⟩.

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

Generated by dwww version 1.15 on Sat Jun 29 00:27:12 CEST 2024.