Provided by: manpages-fr_4.13-4_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 :

       a) avec des descripteurs non bloquants ;

       b) 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).

   Interfaces /proc
       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 d’écoute, 'listen_sock',
              (socket(), bind(), listen()) omitted */

           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 (;;) {
               nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
               if (nfds == -1) {
                   perror("epoll_wait");
                   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
       0.  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).

       1.  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.

       2.  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.

       3.  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.

       4.  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.

       5.  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.

       6.  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))

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

       8.  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.

       9.  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

       L'API epoll a été introduite dans le noyau Linux 2.5.44. Sa prise en charge par la glibc est ajoutée dans
       la version 2.3.2.

CONFORMITÉ

       L'API  epoll  est spécifique à Linux. Certains autres systèmes fournissent des mécanismes similaires. Par
       exemple, FreeBSD propose kqueue et Solaris /dev/poll.

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)

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-Paul Guillonneau <guillonneau.jeanpaul@free.fr>

       Cette  traduction  est  une  documentation libre ; veuillez vous reporter à la GNU General Public License
       version 3 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.

Linux                                              6 mars 2019                                          EPOLL(7)