Provided by: manpages-fr_4.23.1-1_all bug

NOM

       epoll – Notifications d'événements d'entrées et sorties

SYNOPSIS

       #include <sys/epoll.h>

DESCRIPTION

       L'interface  de  programmation  (API)  epoll  réalise  une  tâche  similaire  à  poll(2) :
       surveiller plusieurs descripteurs de fichier pour voir si des E/S y sont possibles.  L'API
       epoll  peut  être déclenchée par changement de niveau ou par changement d'état et s'adapte
       bien à un grand nombre de descripteurs surveillés.

       Le concept central de l’API epoll est l’instance d’epoll, une structure interne  au  noyau
       qui, du point de vue espace utilisateur, peut être considérée comme un conteneur pour deux
       listes :

       -  La liste interest (parfois appelée l’ensemble epoll) : l’ensemble des  descripteurs  de
          fichier que le processus a enregistrés comme intéressants à surveiller.

       -  La  liste  ready :  l’ensemble  des descripteurs de fichier prêts (ready) pour des E/S.
          Cette liste est un sous-ensemble de (plus précisément, un ensemble  de  références  de)
          descripteurs   de   fichier  de  la  liste  interest.  La  liste  ready  est  alimentée
          dynamiquement par le noyau selon le résultat des activités d’E/S de ces descripteurs de
          fichier.

       Les appels système suivants sont fournis pour créer et gérer une instance d’epoll :

       -  epoll_create(2)  crée  une  instance  d’epoll  et  renvoie  un  descripteur  de fichier
          référençant cette instance.  La  version  plus  récente  d'epoll_create1(2)  étend  les
          fonctionnalités d'epoll_create(2).

       -  L'intérêt  pour  des  descripteurs  de fichier particuliers est ensuite enregistré avec
          epoll_ctl(2), qui ajoute les articles dans la liste interest de l’instance d’epoll.

       -  epoll_wait(2) attend les événements d'E/S, en bloquant  le  thread  appelant  si  aucun
          événement  n'est  actuellement  disponible. Cet appel système peut être considéré comme
          recherchant des articles dans la liste ready de l’instance d’epoll.

   Détection par changement de niveau ou d’état
       L'interface de distribution d'événements d’epoll est capable de se comporter en  détection
       de  changement  de  niveau  (Level  Triggered  — LT)  ou  d’état (Edge Triggered — ET). La
       différence entre ces deux mécanismes est décrite ci-dessous.  Supposons  que  le  scénario
       suivant se produise :

       (1)  Le  descripteur  de  fichier  qui  représente  le  côté  lecture  d'un tube (rfd) est
            enregistré dans l'instance d’epoll.

       (2)  Une écriture dans le tube envoie 2 Ko de données du côté écriture du tube.

       (3)  Un appel à epoll_wait(2) est effectué et renvoie rfd  comme  descripteur  de  fichier
            prêt.

       (4)  Un lecteur du tube lit 1 Ko de données depuis rfd.

       (5)  Un appel d’epoll_wait(2) est effectué.

       Si  le  descripteur  rfd  a  été ajouté à l'ensemble epoll en utilisant l'attribut EPOLLET
       (détection  de  changement  d'état),  l'appel  epoll_wait(2),  réalisé  à  l'étape 5,   va
       probablement  bloquer  bien  qu'il  y  ait  des  données toujours présentes dans le tampon
       d'entrée du fichier tandis que le pair distant attendra une réponse basée sur les  données
       qu'il  a  déjà  envoyées.  La  raison en est que le mécanisme de distribution d'événements
       détectés par changement d’état délivre les événements  seulement  lorsque  des  événements
       surviennent  dans le descripteur de fichier supervisé. Ainsi, à l'étape 5, l'appelant peut
       attendre des données qui sont déjà présentes  dans  le  tampon  d'entrée.  Dans  l'exemple
       ci-dessus,  un  événement  sur  rfd  sera  déclenché  à cause de l'écriture à l'étape 2 et
       l'événement est consommé dans l’étape 3. Comme l'opération  de  lecture  de  l'étape 4  ne
       consomme  pas  toutes  les données du tampon, l'appel à epoll_wait(2) effectué à l'étape 5
       peut verrouiller indéfiniment.

       Une application qui emploie l'attribut EPOLLET  de  la  fonction  epoll  devrait  toujours
       utiliser  des descripteurs non bloquants pour éviter qu'une lecture ou une écriture affame
       une tâche qui gère plusieurs descripteurs de  fichier.  L'utilisation  préconisée  d'epoll
       comme interface en détection par changement d’état (EPOLLET) est la suivante :

       (1)  avec des descripteurs non bloquants ;

       (2)  en  attente  d’évènement  seulement  après  qu'un  read(2) ou un write(2) ait renvoyé
            EAGAIN.

       En revanche, lorsqu'il est utilisé avec l'interface en détection par changement de  niveau
       (par  défaut  si  EPOLLET  n'est  pas  spécifié),  epoll est une alternative plus rapide à
       poll(2) et peut être employé à chaque fois que ce dernier est utilisé, car il  utilise  la
       même sémantique.

       Puisque  même  dans  un epoll de type détection le changement d'état, plusieurs événements
       peuvent être générés à la réception de nombreux blocs  de  données,  l'appelant  peut,  en
       spécifiant  l'attribut  EPOLLONESHOT, faire désactiver par epoll le descripteur de fichier
       associé  après  la  réception  d'un  événement  avec  epoll_wait(2).  Lorsque   l'attribut
       EPOLLONESHOT  est  spécifié,  il  est  de  la  responsabilité  de l'appelant de réarmer le
       descripteur en utilisant epoll_ctl(2) avec EPOLL_CTL_MOD.

       Si plusieurs threads (ou processus si les processus enfant ont hérité  du  descripteur  de
       fichier  d’epoll  à  travers  fork(2))  sont bloqués dans epoll_wait(2) en attente du même
       descripteur de fichier d’epoll et qu’un descripteur de fichier dans la liste interest, qui
       est  marqué  pour  une notification par détection de changement d'état (EPOLLET), devienne
       prêt, seul un des threads (ou processus) est réveillé de epoll_wait(2). Cela  fournit  une
       optimisation  utile  pour  éviter  la bousculade de réveils (thundering herd) dans certain
       scénarios.

   Interaction avec autosleep
       Si le système est en mode autosleep à l’aide de /sys/power/autosleep  et  qu’un  événement
       survient  et  sort  le  périphérique de sa veille, le pilote de périphérique ne gardera le
       périphérique actif que jusqu’à la mise en file d’attente de l’événement.  Pour  garder  le
       périphérique   actif   jusqu’au   traitement   de   l’événement,   l’attribut  EPOLLWAKEUP
       d’epoll_ctl(2) doit être utilisé.

       Quand l’attribut EPOLLWAKEUP est défini dans le champ events pour une struct  epoll_event,
       le système sera gardé actif à partir du moment où l’événement est mis en file d’attente, à
       l’aide de l’appel epoll_wait(2) qui  renvoie  l’événement  jusqu’à  l’appel  epoll_wait(2)
       suivant.  Si  l’événement  doit  garder  le  système  actif au delà de ce moment, alors un
       wake_lock séparé devrait être pris avant le second appel à epoll_wait(2).

   /proc interfaces
       Les interfaces suivantes peuvent être utilisées pour limiter la  quantité  de  mémoire  du
       noyau utilisée par epoll :

       /proc/sys/fs/epoll/max_user_watches (depuis Linux 2.6.28)
              Cela  définit  une  limite  au  nombre  total  de  descripteurs  de  fichiers qu'un
              utilisateur peut enregistrer au travers de toutes les instances d’epoll du système.
              La  limite  est  imposée  par identifiant d'utilisateur réel. Chaque descripteur de
              fichier enregistré  coûte  environ  90 octets  sur  un  noyau  32 bits  et  environ
              160 octets   sur   un  noyau  64 bits.  Actuellement  la  valeur  par  défaut  pour
              max_user_watches est de 1/25 (4%) de la mémoire basse  disponible,  divisé  par  le
              coût d'allocation en octets.

   Exemple d'utilisation
       Tandis que l'utilisation d’epoll avec un déclenchement par changement de niveau correspond
       à la même sémantique que poll(2), le déclenchement par changement d'état nécessite plus de
       clarification  pour  éviter  des décrochages dans la boucle d’évènements de l’application.
       Dans cet exemple, l’écouteur emploie un socket non bloquant sur  lequel  listen(2)  a  été
       appelé.  La  fonction do_use_fd() va utiliser le nouveau descripteur de fichier jusqu'à ce
       qu’EAGAIN soit renvoyé par read(2) ou par write(2). Une application d’automate fini piloté
       par  les  évènements  devrait, après réception d'EAGAIN, enregistrer l'état en cours, afin
       que lors de l’appel suivant à do_use_fd(), elle continue avec le read(2) ou le write(2) là
       où elle s'est arrêtée.

           #define MAX_EVENTS 10
           struct epoll_event ev, events[MAX_EVENTS];
           int listen_sock, conn_sock, nfds, epollfd;

           /* Code pour régler le socket à l’écoute, 'listen_sock',
              (socket(), bind(), listen()) omis. */

           epollfd = epoll_create1(0);
           if (epollfd == -1) {
               perror("epoll_create1");
               exit(EXIT_FAILURE);
           }

           ev.events = EPOLLIN;
           ev.data.fd = listen_sock;
           if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
               perror("epoll_ctl: listen_sock");
               exit(EXIT_FAILURE);
           }

               for (n = 0; n < nfds; ++n) {
                   if (events[n].data.fd == listen_sock) {
                       conn_sock = accept(listen_sock,
                                          (struct sockaddr *) &addr, &addrlen);
                       if (conn_sock == -1) {
                           perror("accept");
                           exit(EXIT_FAILURE);
                       }
                       setnonblocking(conn_sock);
                       ev.events = EPOLLIN | EPOLLET;
                       ev.data.fd = conn_sock;
                       if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
                                   &ev) == -1) {
                           perror("epoll_ctl : conn_sock");
                           exit(EXIT_FAILURE);
                       }
                   } else {
                       do_use_fd(events[n].data.fd);
                   }
               }
           }

       Lorsqu'on  utilise  une détection de changement d'états, pour des raisons de performances,
       il  est  possible  d'ajouter  le  descripteur  de   fichier   dans   l'interface   d’epoll
       (EPOLL_CTL_ADD) après, en spécifiant (EPOLLIN|EPOLLOUT). Cela évite de basculer sans cesse
       entre EPOLLIN et EPOLLOUT lors des appels epoll_ctl(2) avec EPOLL_CTL_MOD.

   Questions/Réponses
       -  Quelle est la clé utilisée pour distinguer les descripteurs de fichier enregistrés dans
          une liste interest ?

          La  clé est une combinaison du numéro du descripteur de fichier et de la description du
          fichier ouvert (aussi connue comme « open file handle », la représentation  interne  au
          noyau d'un fichier ouvert).

       -  Que  se  passe-t-il  si on enregistre deux fois le même descripteur de fichier dans une
          instance d’epoll ?

          Vous aurez probablement un EEXIST. Cependant il est possible d'ajouter un duplicata  de
          descripteur  (dup(2),  dup2(2), F_DUPFD de fcntl(2)) sur la même instance d’epoll. Cela
          peut être une technique utile  pour  le  filtrage  d'événements,  si  les  descripteurs
          dupliqués sont enregistrés avec des masques events différents.

       -  Deux  instances d’epoll peuvent-elles attendre le même descripteur de fichier ? Si oui,
          les événements seront-ils reportés sur les deux descripteurs de fichier d’epoll ?

          Oui, et les événements seront rapportés aux deux. Toutefois, une programmation  soignée
          est nécessaire pour que cela soit fait correctement.

       -  Est-ce que le descripteur d’epoll lui-même est sujet à poll/epoll/select ?

          Oui.  Si  un  descripteur  de  fichier  d’epoll  a  des événements en attente, alors il
          indiquera qu'il est lisible.

       -  Que se passe-t-il si on cherche  à  placer  un  descripteur  d’epoll  dans  son  propre
          ensemble de descripteurs de fichier  ?

          L'appel  epoll_ctl(2)  échouera  (EINVAL). Toutefois vous pouvez ajouter un descripteur
          d’epoll dans un autre ensemble de descripteurs de fichier d’epoll.

       -  Puis-je envoyer le  descripteur  d’epoll  à  travers  un  socket  UNIX  vers  un  autre
          processus ?

          Oui, mais il n'y a aucune raison de faire ça, puisque le processus récepteur n'aura pas
          de copie des descripteurs de fichier de la liste interest.

       -  Est-ce que la fermeture d'un descripteur le  supprime  automatiquement  de  toutes  les
          listes interest d’epoll ?

          Oui,  mais prenez note des points suivants. Un descripteur de fichier est une référence
          vers la description d'un fichier  ouvert  (consultez  open(2)).  À  chaque  fois  qu'un
          descripteur  est  dupliqué  avec  dup(2),  dup2(2),  F_DUPFD de fcntl(2) ou fork(2), un
          nouveau descripteur de fichier qui se réfère au  même  fichier  ouvert  est  créé.  Une
          description  de  fichier ouvert continue d'exister jusqu'à ce que tous les descripteurs
          de fichier qui s'y réfèrent soient fermés.

          Un descripteur de fichier n'est retiré d'une liste interest qu'après  la  fermeture  de
          tous  les  descripteurs  de  fichier qui se réfèrent à la description de fichier ouvert
          sous-jacente. Cela signifie que même après la fermeture  d'un  descripteur  de  fichier
          faisant  partie  de cette liste, des événements peuvent toujours être rapportés pour ce
          descripteur de fichier si d'autres descripteurs de  fichier,  se  référant  à  la  même
          description   de   fichier  sous-jacente,  restent  ouverts.  Pour  empêcher  cela,  le
          descripteur de fichier doit être explicitement  supprimé  de  la  liste  (en  utilisant
          epoll_ctl(2) EPOLL_CTL_DEL) avant qu’il ne soit dupliqué. Autrement, l’application doit
          assurer que tous les descripteurs soient fermés (ce qui  peut  être  difficile  si  les
          descripteurs ont été dupliqués en dehors du cadre par des fonctions de bibliothèque qui
          utilisent dup(2) ou fork(2))

       -  Si plus d'un événement surviennent entre deux appels epoll_wait(2),  sont-ils  combinés
          ou rapportés séparément ?

          Ils sont combinés.

       -  Est-ce  qu'une  opération sur un descripteur affecte les événements déjà collectés mais
          pas encore rapportés ?

          Vous pouvez faire deux choses sur un descripteur existant. Une suppression serait  sans
          effet dans ce cas. Une modification revérifie les entrées et sorties disponibles.

       -  Dois-je  lire/écrire  sans  cesse  un  descripteur jusqu'à obtenir EAGAIN si l'attribut
          EPOLLET est utilisé (comportement par détection de changement d'état) ?

          La réception d'un événement depuis epoll_wait(2) suggère  qu'un  descripteur  est  prêt
          pour  l'opération  d'E/S  désirée.  Il doit être considéré comme prêt jusqu'à ce que la
          prochaine lecture ou écriture (non bloquante)  remonte  un  EAGAIN.  Quand  et  comment
          utiliser le descripteur dépend de vous.

          Pour  les  fichiers  orientés  paquet ou jeton (par exemple, un socket datagramme ou un
          terminal en mode canonique), la seule façon de détecter la fin de l'espace d'entrée  et
          sortie  pour  les  lectures  ou  écritures est de continuer à lire ou écrire jusqu'à la
          réception d'un EAGAIN.

          Pour les fichiers orientés flux (par exemple, les tubes, FIFO ou sockets en mode flux),
          la  disponibilité  des  entrées  et  sorties  peut  aussi être détectée en vérifiant la
          quantité de données lues ou écrites sur le descripteur. Par exemple,  si  vous  appelez
          read(2)  en  demandant  la lecture d'une certaine quantité de données et que read(2) en
          renvoie moins, vous pouvez être sûr d'avoir consommé tout le tampon  d'entrée  pour  le
          descripteur.  La  même  chose  est  vraie  pour  l'appel système write(2) (évitez cette
          dernière technique si vous ne  pouvez  pas  garantir  que  le  descripteur  de  fichier
          surveillé corresponde toujours à un fichier de type flux).

   Erreurs possibles et moyens de les éviter
       -  Famine (détection par changement d'état)

          S'il  y a un gros volume d’espace d’E/S, il est possible qu'en essayant de les traiter,
          d'autres fichiers ne soient pas pris en compte provoquant une famine. Ce problème n'est
          pas spécifique à epoll.

          La  solution  est  de  maintenir  une  liste  de  descripteurs  prêts  et de marquer le
          descripteur de fichier prêt dans leur structure associée, permettant à l'application de
          savoir  quels  fichiers traiter mais toujours en tourniquet englobant tous les fichiers
          prêts. Cela permet aussi d'ignorer  les  événements  ultérieurs  sur  des  descripteurs
          prêts.

       -  En cas d’utilisation d'un cache d'événements...

          Si  vous  utilisez un cache d'événements, ou stockez tous les descripteurs renvoyés par
          epoll_wait(2), alors assurez-vous de disposer d'un moyen de marquer dynamiquement leurs
          fermetures  (c’est-à-dire  causées  par un traitement d’événement précédent). Supposons
          que vous recevez 100 événements  d’epoll_wait(2)  et  que  l'événement 47  implique  de
          fermer  l’évènement 13.  Si  vous  supprimez  la structure et utilisez close(2) pour le
          descripteur de fichier pour l’évènement 13, alors votre cache peut encore contenir  des
          événements pour ce descripteur, posant alors des problèmes de confusion.

          Une    solution    est   d'invoquer,   pendant   le   traitement   de   l'événement 47,
          epoll_ctl(EPOLL_CTL_DEL) pour supprimer le descripteur 13,  le  fermer  avec  close(2),
          puis marquer sa structure associée comme supprimée et la lier à une liste de nettoyage.
          Si vous rencontrez un autre événement pour le  descripteur 13  dans  votre  traitement,
          vous verrez qu'il a été supprimé précédemment sans que cela ne prête à confusion.

VERSIONS

       Certains  autres  systèmes  fournissent  des  mécanismes  similaires. Par exemple, FreeBSD
       propose kqueue et Solaris /dev/poll.

STANDARDS

       Linux.

HISTORIQUE

       Linux 2.5.44. glibc 2.3.2.

NOTES

       L’ensemble des descripteurs de fichier qui sont supervisés par un descripteur  de  fichier
       d’epoll  peut  être  visualisé à l’aide de l’entrée pour le descripteur de fichier d’epoll
       dans le répertoire /proc/pid/fdinfo du processus. Consultez proc(5) pour plus de détails.

       L’opération KCMP_EPOLL_TFD de kcmp(2) peut être utilisée pour tester si un descripteur  de
       fichier est présent dans une instance d’epoll.

VOIR AUSSI

       epoll_create(2), epoll_create1(2), epoll_ctl(2), epoll_wait(2), poll(2), select(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>  et  Jean-Paul  Guillonneau
       <guillonneau.jeanpaul@free.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⟩.