Loading

NOM

       select,  pselect,  FD_CLR,  FD_ISSET,  FD_SET,  FD_ZERO  - Multiplexage
       d’entrées-sorties synchrones.

SYNOPSIS

       /* D’après POSIX.1-2001 */
       #include <sys/select.h>

       /* D’après les standards précédents */
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

       void FD_CLR(int fd, fd_set *set);
       int  FD_ISSET(int fd, fd_set *set);
       void FD_SET(int fd, fd_set *set);
       void FD_ZERO(fd_set *set);

       #include <sys/select.h>

       int pselect(int nfds, fd_set *readfds, fd_set *writefds,
                   fd_set *exceptfds, const struct timespec *timeout,
                   const sigset_t *sigmask);

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

       pselect() : _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >=600

       select() et pselect() permettent à 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. Un descripteur de fichier  est  considéré  comme  prêt
       s’il  est  possible d’effectuer l’opération correspondante (par exemple
       read(2)) sans bloquer.

       select()  et  pselect()  ont  un  comportement  identique,  avec  trois
       différences :

       (i)    La  fonction  select()  utilise un délai exprimé avec une struct
              timeval (secondes et microsecondes), alors que pselect() utilise
              une struct timespec (secondes et nanosecondes).

       (ii)   La  fonction  select()  peut  modifier le paramètre timeout pour
              indiquer le temps restant. La fonction pselect() ne  change  pas
              ce paramètre.

       (iii)  La fonction select() n’a pas de paramètre sigmask et se comporte
              comme pselect() avec une valeur NULL pour sigmask

       Il  y  a  trois  ensembles  indépendants  de  descripteurs   surveillés
       simultanément.  Ceux  de  l’ensemble  readfds  seront  surveillés  pour
       vérifier si des caractères  deviennent  disponibles  en  lecture.  Plus
       précisément,  on vérifie si un appel système de lecture ne bloquera pas
       — en particulier un descripteur en fin de fichier sera considéré  comme
       prêt.  Les  descripteurs  de l’ensemble writefds seront surveillés pour
       vérifier si une écriture ne bloquera  pas.  Ceux  de  exceptfds  seront
       surveillés  pour l’occurrence de conditions exceptionnelles. En sortie,
       les ensembles sont modifiés pour  indiquer  les  descripteurs  qui  ont
       changé  de  statut. Chacun des trois ensemble de descripteurs peut être
       NULL si aucun descripteur de fichier ne doit être surveillé pour  cette
       classe d’événements.

       Quatre  macros  sont  disponibles  pour  la manipulation des ensembles.
       FD_ZERO()  efface  un  ensemble.  FD_SET()  et  FD_CLR()  ajoutent   et
       suppriment  un  descripteur  dans un ensemble. FD_ISSET() vérifie si un
       descripteur est contenu dans un ensemble, principalement utile après le
       retour de select().

       nfds est le numéro du plus grand descripteur des 3 ensembles, plus 1.

       timeout  est  une  limite supérieure au temps passé dans select() avant
       son retour. Si les deux champs de la structure timeval sont nuls  alors
       select() retourne immédiatement. (Ce qui sert pour des surveillances en
       polling). Si le timeout est NULL (aucune limite), select() peut bloquer
       indéfiniment.

       sigmask est un pointeur sur un masque de signaux (voir 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.

       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;

           sigprocmask(SIG_SETMASK, &sigmask, &origmask);
           ready = select(nfds, &readfds, &writefds, &exceptfds, timeout);
           sigprocmask(SIG_SETMASK, &origmask, NULL);

       L’idée derrière pselect() est que pour l’attente d’un événement, que ce
       soit  un  signal  ou une condition sur un descripteur, un test atomique
       est nécessaire pour éviter les situations  de  concurrence.  (Supposons
       que  le  gestionnaire  de signaux active un drapeau global et revienne.
       Alors un test de ce drapeau, suivi d’un  appel  select()  peut  bloquer
       indéfiniment  si  le  signal  arrive  juste  après  le  test mais avant
       l’appel. À l’inverse, pselect() permet de bloquer  le  signal  d’abord,
       traiter  les  signaux  déjà  reçus,  puis  invoquer  pselect()  avec le
       sigmask, désiré, en évitant la situation de blocage.)

   Délai maximal
       Les structures temporelles concernées sont définies  dans  <sys/time.h>
       comme ceci :

           struct timeval {
               long    tv_sec;         /* secondes      */
               long    tv_usec;        /* microsecondes */
           };

       et

           struct timespec {
               long    tv_sec;         /* secondes     */
               long    tv_nsec;        /* nanosecondes */
           };

       (Toutefois, voir plus loin les versions POSIX.1-2001.)

       Certaines  applications  appellent  select()  avec  trois  ensembles de
       descripteurs vides, nfds  nul,  et  un  délai  timeout  non  nul,  afin
       d’endormir,  de  manière portable, le processus avec une précision plus
       fine que la seconde.

       Sous Linux, la fonction select() modifie timeout pour indiquer le temps
       restant  mais  la  plupart  des  autres  implémentations ne le font pas
       (POSIX.1-2001 autorise les deux comportements). Ceci 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 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   retournés
       (c’est-à-dire  le  nombre  total  de  bits  à 1 dans readfds, writefds,
       exceptfds) qui peut être nul si le délai de timeout a expiré avant  que
       quoi  que ce soit d’intéressant ne se produise. Ils retournent -1 s’ils
       échouent, auquel cas errno contient le code d’erreur ; les ensembles et
       timeout  ne  sont  plus définis, ne vous fiez plus à leur contenu après
       une erreur.

ERREURS

       EBADF  Un  descripteur  de  fichier  invalide  était  dans   l’un   des
              ensembles.  (Peut-être  un descripteur déjà fermé, ou sur lequel
              une erreur s’est produite.)

       EINTR  Un signal a été intercepté ; voir signal(7).

       EINVAL nfds  est  négatif  ou  la  valeur  contenue  dans  timeout  est
              invalide.

       ENOMEM Pas assez de mémoire pour le noyau.

VERSIONS

       pselect()  a  été  ajouté  à  Linux dans le noyau 2.6.16. Précédemment,
       pselect() était émulé dans la glibc (mais voir la section BOGUES).

CONFORMITÉ

       select() est conforme à POSIX.1-2001 et BSD 4.4 (la  fonction  select()
       est  apparue  dans  BSD 4.2).  Généralement portable depuis ou vers des
       systèmes non-BSD supportant des clones de  la  couche  sockets  BSD  (y
       compris les variantes du System V). Néanmoins, sachez que les variantes
       du System V fixent une variable de timeout avant le  retour  alors  que
       les variantes BSD ne le font pas.

       pselect() est défini dans POSIX.1g, et dans POSIX.1-2001.

NOTES

       Un  ensemble  fd_set est un tampon de taille fixe. Exécuter FD_CLR() ou
       FD_SET() avec fd négatif ou supérieur ou égal à FD_SETSIZE résultera en
       un  comportement  indéfini.  Plus  encore, POSIX demande que fd soit un
       descripteur de fichier valide.

       En ce qui concerne les types impliqués, la situation classique est  que
       les  deux champs de la structure timeval soient de type « long » (comme
       ci-dessus), et que la structure  soit  définie  dans  <sys/time.h>.  La
       situation avec POSIX.1-2001 est

           struct timeval {
               time_t         tv_sec;     /* secondes */
               suseconds_t    tv_usec;    /* microsecondes */
           };

       avec  la  structure définie dans <sys/select.h> et les types de données
       time_t et suseconds_t définis dans <sys/types.h>.

       Concernant les prototypes,  on  demande  classiquement  l’inclusion  de
       <time.h>   pour   select().   Avec  POSIX.1-2001,  on  préfère  inclure
       <sys/select.h> pour select() et pselect().

       Les   bibliothèques   libc4   et   libc5   n’avaient   pas    d’en-tête
       <sys/select.h>, mais avec les glibc 2.0 et suivantes le fichier existe.
       Pour la glibc 2.0, le prototype de pselect() est toujours erroné.  Avec
       la  glibc  2.1  à  2.2.1  le  prototype  de  pselect() est fourni si la
       constante _GNU_SOURCE est définie avant l’inclusion.  Depuis  la  glibc
       2.2.2, les exigences sont celles indiquées dans le SYNOPSIS.

   Notes sur Linux
       L’appel  système  pselect()  de  Linux  modifie  son  argument timeout.
       Cependant, la fonction d’enrobage de la glibc cache ce comportement  en
       utilisant  une  variable locale pour l’argument timeout qui est passé à
       l’appel système. Par conséquent, la  fonction  pselect()  de  glibc  ne
       modifie  pas  son argument timeout, ce qui est le comportement prescrit
       par POSIX.1-2001.

BOGUES

       Glibc  2.0  fournissait  une  version  de  pselect()  qui  n’avait  pas
       d’argument sigmask.

       Depuis  la  version  2.1,  la  glibc fournit une émulation de pselect()
       implémentée avec sigprocmask(2) et select(). Cette  implémentation  est
       vulnérable  à  la condition de concurrence que pselect() est conçu pour
       éviter. Sur les systèmes sans pselect, une gestion plus sûre  (et  plus
       portable)  des  signaux  peut  être  obtenue  en  utilisant un tube (un
       gestionnaire de signal écrit un octet dans un tube dont  select()  dans
       le programme principal surveille l’autre extrémité).

       Sous  Linux,  select()  peut  signaler un descripteur de fichier socket
       comme « prêt à lire » alors qu’une lecture suivante bloque. Cela  peut,
       par  exemple,  survenir  lorsque  des données sont arrivées mais, après
       vérification, ont une mauvaise somme de contrôle et sont rejetées. Cela
       peut  également arriver dans d’autres circonstances. Aussi, il est plus
       sûr d’utiliser O_NONBLOCK sur des sockets qui ne devraient pas bloquer.

       Sous   Linux,   select()  modifie  également  timeout  si  l’appel  est
       interrompu par un gestionnaire de signaux (code d’erreur  EINTR).  Ceci
       est  interdit  par  POSIX.1-2001. 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.

EXEMPLE

       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int
       main(void)
       {
           fd_set rfds;
           struct timeval tv;
           int retval;

           /* Surveiller stdin (fd 0) en attente d’entrées */
           FD_ZERO(&rfds);
           FD_SET(0, &rfds);

           /* Attends jusqu’à 5 secondes. */
           tv.tv_sec = 5;
           tv.tv_usec = 0;

           retval = select(1, &rfds, NULL, NULL, &tv);
           /* Considérer tv comme indéfini 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

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

       D’autres pages ayant un vague rapport : accept(2), connect(2), poll(2),
       read(2), recv(2), send(2), sigprocmask(2), write(2), epoll(7), time(7)

COLOPHON

       Cette  page  fait  partie  de  la  publication 3.23 du projet man-pages
       Linux. Une description du projet et des instructions pour signaler  des
       anomalies       peuvent       être       trouvées      à      l’adresse
       http://www.kernel.org/doc/man-pages/.

TRADUCTION

       Cette page de manuel a été traduite  et  mise  à  jour  par  Christophe
       Blaess  <http://www.blaess.fr/christophe/> entre 1996 et 2003, puis par
       Alain Portal <aportal AT univ-montp2 DOT fr> jusqu’en 2006, et  mise  à
       disposition sur http://manpagesfr.free.fr/.

       Les mises à jour et corrections de la version présente dans Debian sont
       directement gérées par Julien Cristau <jcristau@debian.org> et l’équipe
       francophone de traduction de Debian.

       Veuillez   signaler   toute   erreur   de   traduction  en  écrivant  à
       <debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
       paquet manpages-fr.

       Vous  pouvez  toujours avoir accès à la version anglaise de ce document
       en utilisant la commande « man -L C <section> <page_de_man> ».