Provided by: manpages-fr-dev_4.13-4_all bug

NOM

       poll, ppoll - Attendre un événement concernant un descripteur de fichier

SYNOPSIS

       #include <poll.h>

       int poll(struct pollfd *fds, nfds_t nfds, int timeout);

       #define _GNU_SOURCE         /* Consultez feature_test_macros(7) */
       #include <signal.h>
       #include <poll.h>

       int ppoll(struct pollfd *fds, nfds_t nfds,
               const struct timespec *tmo_p, const sigset_t *sigmask);

DESCRIPTION

       poll()  fait  la même chose que select(2) : il attend que l'un des descripteurs de fichier
       soit prêt pour des entrées et sorties. L'API de epoll(7) spécifique à Linux fait  la  même
       chose, mais avec des fonctionnalités allant au-delà de celles de poll().

       L'ensemble de descripteurs de fichier à surveiller est indiqué dans l'argument fds qui est
       un tableau de structures de la forme suivante :

           struct pollfd {
               int   fd;         /* Descripteur de fichier */
               short events;     /* Événements attendus    */
               short revents;    /* Événements détectés    */
           };

       L'appelant doit spécifier le nombre d'éléments du tableau fds dans nfds.

       Le champ fd contient un descripteur de fichier pour un fichier ouvert.  Si  ce  champ  est
       négatif,  alors  le champ events correspondant est ignoré et le champ revents renvoie zéro
       (cela permet d'ignorer facilement un descripteur de fichier pour un seul appel poll() : il
       suffit  d'utiliser  l'opposé du champ fd ; remarquez cependant que cette technique ne peut
       pas être utilisée pour ignorer le descripteur de fichier 0).

       Le champ events est un paramètre d'entrée, un masque de bits indiquant les événements  qui
       intéressent  l'application  pour  le  descripteur  de  fichier fd. Ce champ peut être nul,
       auquel cas les seuls événements qui peuvent  être  renvoyés  dans  revents  sont  POLLHUP,
       POLLERR et POLLNVAL (voir ci-dessous).

       Le  champ  revents est un paramètre de sortie, rempli par le noyau avec les événements qui
       se sont effectivement produits, d'un des types demandés par events ou de l'une des valeurs
       POLLERR,  POLLHUP  ou POLLNVAL. (Ces trois bits n'ont pas de signification dans la demande
       events et se trouvent positionnés dans la valeur de retour revents si l'une des conditions
       correspondantes se produit.)

       Si aucun événement attendu (ni aucune erreur) ne s'est déjà produit, poll() bloque jusqu'à
       ce que l'un des événements se produise.

       L'argument timeout définit le temps en milliseconde pendant lequel poll() devrait  bloquer
       en  attendant  que  le descripteur de fichier soit prêt. L’appel bloquera jusqu’au premier
       événement suivant :

         •
         un descripteur de fichier devient prêt ;

         •
         l’appel est interrompu par un gestionnaire de signal ;

         •
         le délai expire.

       Remarquez que l’intervalle timeout sera arrondi à la granularité de l'horloge  système  et
       que  les  délais d'ordonnancement du noyau signifient que l'intervalle de blocage pourrait
       être dépassé d'une petite quantité. Une valeur  négative  de  timeout  signifie  un  délai
       infini,  alors  qu'un timeout nul force epoll() à se terminer immédiatement, même si aucun
       descripteur de fichier n'est prêt.

       Les bits qui peuvent être activés ou renvoyés dans events  et  revents  sont  définis  par
       <poll.h> :

       POLLIN Il y a des données en attente de lecture.

       POLLPRI
              Il  existe  une  condition  d'exception sur le descripteur de fichier. Parmi celles
              possibles :

                •
                Des données dépassent sur un socket TCP (voir tcp(7)).

                •
                Un pseudoterminal maître en mode paquet a vu un changement d'état  sur  l'esclave
                (voir ioctl_tty(2)).

                •
                Un fichier cgroup.events a été modifié (voir cgroups(7)).

       POLLOUT
              L'écriture  est  maintenant  possible,  mais  une écriture plus grande que l'espace
              disponible sur un socket ou  un  tube  bloquera  encore  (sauf  si  O_NONBLOCK  est
              positionné).

       POLLRDHUP (depuis Linux 2.6.17)
              Le  correspondant sur un socket en mode flux a fermé la connexion ou bien a terminé
              la partie écriture de la connexion. La macro de test de fonctionnalité  _GNU_SOURCE
              doit  être  définie  (avant  d'inclure  tout  fichier d'en‐tête) pour obtenir cette
              définition.

       POLLERR
              Condition d'erreur (renvoyée seulement dans revents ; ignorée dans events). Ce  bit
              est  aussi  positionné  pour  un  descripteur  de fichier qui se rapporte à une fin
              d'écriture sur un tube lorsque la fin de lecture a été fermée.

       POLLHUP
              Plantage (renvoyé seulement dans revents ; ignoré  dans  events).  Remarquez  qu'en
              lecture  à  partir  d'un  canal  tel qu'un tube ou un socket de flux, cet événement
              indique simplement que le pair a fermé la fin de son canal. Les lectures  suivantes
              à  partir du canal ne renverront 0 (fin de fichier) qu'après que toutes les données
              du canal aient été consommées.

       POLLNVAL
              Requête non valable : fd n'est pas ouvert (renvoyé seulement dans revents ;  ignoré
              dans events).

       Lorsque  _XOPEN_SOURCE  est  défini  à la compilation, les macros suivantes sont également
       définies (mais n'apportent pas d'informations supplémentaires par rapport aux bits  listés
       ci‐dessus :

       POLLRDNORM
              Équivalent à POLLIN.

       POLLRDBAND
              Des  données  prioritaires  sont en attente de lecture (généralement inutilisé sous
              Linux).

       POLLWRNORM
              Équivalent à POLLOUT.

       POLLWRBAND
              Des données prioritaires peuvent être écrites.

       Linux connaît aussi POLLMSG, mais ne l'utilise pas.

   ppoll()
       La relation entre poll() et ppoll()  est  similaire  à  la  relation  entre  select(2)  et
       pselect(2) :  comme  pselect(2), ppoll() permet à une application d'attendre de façon sûre
       que soit un descripteur de fichier soit prêt, soit un signal soit reçu.

       Mise à part la différence de précision de l'argument timeout, l'appel ppoll() suivant :

           ready = ppoll(&fds, nfds, tmo_p, &sigmask);

       est presque équivalent à exécuter de façon atomique les appels suivants :

           sigset_t origmask;
           int timeout;

           timeout = (tmo_p == NULL) ? -1 :
                     (tmo_p->tv_sec * 1000 + tmo_p->tv_nsec / 1000000);
           pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
           ready = poll(&fds, nfds, timeout);
           pthread_sigmask(SIG_SETMASK, &origmask, NULL);

       Le bout de code ci-dessus est décrit comme presque équivalent parce qu’une valeur négative
       dans  *tmo_p  donne  une  erreur de ppoll(), tandis qu’une valeur négative de timeout pour
       poll() est interprétée comme un délai infini.

       Consultez la description de pselect(2) pour une explication de la nécessité de ppoll().

       Si le paramètre sigmask est défini comme NULL, aucune manipulation de  masque  de  signaux
       n'est  effectuée (et ainsi ppoll() ne diffère de poll() que dans la précision du paramètre
       timeout).

       L'argument tmo_p définit une  limite  supérieure  sur  le  temps  pendant  lequel  ppoll()
       bloquera. Cet argument est un pointeur vers une structure de la forme suivante :

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

       Si tmo_p est NULL, ppoll() pourra bloquer indéfiniment.

VALEUR RENVOYÉE

       En cas de succès, poll() renvoie une valeur non négative qui est un nombre d'éléments dans
       pollfds dont les champs revents  ont  été  positionnés  sur  une  autre  valeur  que  zéro
       (indiquant  un  événement  ou  une  erreur). Un code de retour de zéro indique que l'appel
       système a atteint son délai avant qu'un descripteur de fichier ne soit lu.

       En cas d'erreur, la valeur de retour est -1 et errno est définie pour indiquer la cause de
       l'erreur.

ERREURS

       EFAULT fds pointe hors de l'espace d'adressage accessible. Le tableau donné en argument ne
              se trouvait pas dans l'espace d'adressage du programme appelant.

       EINTR  Un signal a été reçu avant  qu'un  événement  intéressant  ne  se  produise ;  voir
              signal(7).

       EINVAL La valeur nfds dépasse la valeur RLIMIT_NOFILE.

       EINVAL (ppoll()) La valeur du délai exprimée dans *ip n'est pas valable (négative).

       ENOMEM Impossible d'allouer de la mémoire pour des structures de données du noyau.

VERSIONS

       L'appel  système poll() a été introduit dans Linux 2.1.23. Sur les anciens noyaux sans cet
       appel système, la fonction enveloppe poll() de la glibc fournit une émulation en utilisant
       select(2).

       L'appel  système  ppoll()  a  été introduit dans Linux 2.6.16. La fonction de bibliothèque
       correspondante a été ajoutée dans la glibc 2.4.

CONFORMITÉ

       poll() est conforme à POSIX.1-2001 et POSIX.1-2008. ppoll() est spécifique à Linux.

NOTES

       L'opération de poll() et ppoll() n'est pas concernée par l'attribut O_NONBLOCK.

       Sur d'autres systèmes UNIX, poll()  peut  échouer  avec  l'erreur  EAGAIN  si  le  système
       n'arrive  pas  à  allouer  des  ressources internes au noyau, et non avec ENOMEM comme sur
       Linux. POSIX autorise ce comportement. Les programmes portables peuvent  vouloir  vérifier
       EAGAIN et tourner en boucle, comme avec EINTR.

       Certaines  implémentations  définissent  la  constante  symbolique  non standard INFTIM de
       valeur -1, à utiliser comme timeout pour poll(). Cette constante n'est pas fournie par  la
       glibc.

       Consultez  select(2)  pour une discussion sur ce qui pourrait arriver si un descripteur de
       fichier surveillé par poll() est fermé dans un autre thread.

   différences entre bibliothèque C et noyau
       L'appel système ppoll() sous Linux modifie  son  argument  tmo_p.  Cependant,  l'enveloppe
       fournie  par la glibc cache ce comportement en utilisant une variable locale pour le délai
       qui est fournie à l'appel système. Ainsi, la fonction ppoll() de la glibc ne modifie  donc
       pas son argument tmo_p.

       L'appel  système  ppoll() brut a un cinquième paramètre, size_t sigsetsize, qui indique la
       taille en octets du paramètre sigmask. La fonction enveloppe ppoll() de la  glibc  indique
       ce  paramètre comme une valeur fixe (égale à sizeof(kernel_sigset_t)). Voir sigprocmask(2)
       pour un point sur les différences entre l'approche du noyau et de la libc de sigset.

BOGUES

       Consultez la discussion sur les notifications  non  voulues  dans  la  section  BOGUES  de
       select(2).

EXEMPLES

       Le programme ci-dessous ouvre chacun des fichiers nommés sur ses paramètres de la ligne de
       commande et  surveille  les  descripteurs  de  fichier  qui  en  résultent  quand  à  leur
       possibilité  d'être  lus  (POLLIN).  Le  programme  effectue  une  boucle  de  poll() pour
       surveiller les descripteurs de fichier, affichant en retour le nombre de  descripteurs  de
       fichier prêts. Pour chaque descripteur disponible, le programme :

         •
         affiche le champ revents renvoyé sous une forme lisible par un humain ;

         •
         si  le  descripteur de fichier est lisible, y lit des données et affiche ces données sur
         la sortie standard ; et

         •
         si le descripteur de fichier n'était  pas  lisible  mais  qu'un  autre  événement  s'est
         produit (probablement POLLHUP), ferme le descripteur de fichier.

       Supposons qu'on lance le programme dans un terminal, en lui demandant d'ouvrir un FIFO :

           $ mkfifo monfifo
           $ ./poll_input monfifo

       Dans  une deuxième fenêtre de terminal, on ouvre alors le FIFO en écriture, on y écrit des
       données et on ferme le FIFO :

           $ echo aaaaabbbbbccccc > monfifo

       Dans le terminal où on exécute le programme, on verrait alors :

           "monfifo" ouvert sur le fd 3
           Préparation pour poll()
           Prêt : 1
             fd=3 ; événements: POLLIN POLLHUP
               10 octets lus : aaaaabbbbb
           Va poll()
           Prêt : 1
             fd=3 ; événements : POLLIN POLLHUP
               lecture de 6 octets : ccccc

           Préparation pour poll()
           Prêt : 1
             fd=3 ; événements : POLLHUP
               fermeture de fd 3
           Tous les descripteurs de fichier sont fermés ; au revoir

       Dans la sortie ci-dessus, on voit que poll() a renvoyé trois fois :

         •
         Sur le premier retour, les bits renvoyés dans le champ revents étaient POLLIN, indiquant
         que  le  descripteur de fichier est lisible, et POLLHUP, indiquant que l'autre extrémité
         du FIFO a été fermée. Puis le programme a consommé une partie de l'entrée disponible.

         •
         Le deuxième retour de poll() indiquait aussi POLLIN et POLLHUP ; le  programme  a  alors
         consommé la dernière partie de l’entrée disponible.

         •
         Sur  le  dernier  retour,  poll()  n'indiquait  que  POLLHUP sur le FIFO, lemoment où le
         descripteur de fichier a été fermé et où le programme s'est terminé.

   Source du programme

       /* poll_input.c

          Sous licence GNU General Public License v2 ou postérieure.
       */
       #include <poll.h>
       #include <fcntl.h>
       #include <sys/types.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>

       #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                               } while (0)

       int
       main(int argc, char *argv[])
       {
           int nfds, num_open_fds;
           struct pollfd *pfds;

           if (argc < 2) {
              fprintf(stderr, "Utilisation : %s fichier...\n", argv[0]);
              exit(EXIT_FAILURE);
           }

           num_open_fds = nfds = argc - 1;
           pfds = calloc(nfds, sizeof(struct pollfd));
           if (pfds == NULL)
               errExit("malloc");

           /* Ouvrir chaque fichier de la ligne de commande et l'ajouter au tableau
              'pfds' */

           for (int j = 0; j < nfds; j++) {
               pfds[j].fd = open(argv[j + 1], O_RDONLY);
               if (pfds[j].fd == -1)
                   errExit("open");

               printf("\"%s\" ouvert sur le fd %d\n", argv[j + 1], pfds[j].fd);

               pfds[j].events = POLLIN;
           }

           /* Conserver poll() au moins aussi longtemps qu'un descripteur de fichier
              est ouvert */

           while (num_open_fds > 0) {
               int ready;

               printf("Va poll()\n");
               ready = poll(pfds, nfds, -1);
               if (ready == -1)
                   errExit("poll");

               printf("Prêt : %d\n", ready);

               /* Gérer le tableau renvoyé par poll() */

               for (int j = 0; j < nfds; j++) {
                   char buf[10];

                   if (pfds[j].revents != 0) {
                       printf("  fd=%d ; événements : %s%s%s\n", pfds[j].fd,
                               (pfds[j].revents & POLLIN)  ? "POLLIN "  : "",
                               (pfds[j].revents & POLLHUP) ? "POLLHUP " : "",
                               (pfds[j].revents & POLLERR) ? "POLLERR " : "");

                       if (pfds[j].revents & POLLIN) {
                           ssize_t s = read(pfds[j].fd, buf, sizeof(buf));
                           if (s == -1)
                               errExit("read");
                           printf("    lecture de %zd octets : %.*s\n",
                                   s, (int) s, buf);
                       } else {                /* POLLERR | POLLHUP */
                           printf("    fermeture du fd %d\n", pfds[j].fd);
                           if (close(pfds[j].fd) == -1)
                               errExit("close");
                           num_open_fds--;
                       }
                   }
               }
           }

           printf("Tous les descripteurs de fichier sont fermés ; au revoir\n");
           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

       restart_syscall(2), select(2), select_tut(2), epoll(7), time(7)

COLOPHON

       Cette page fait partie de la publication 5.10 du projet man-pages Linux.  Une  description
       du  projet et des instructions pour signaler des anomalies et la dernière version de cette
       page peuvent être trouvées à l'adresse https://www.kernel.org/doc/man-pages/.

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> et Jean-Philippe MENGUAL
       <jpmengual@debian.org>

       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 ⟨⟩.