Provided by: manpages-fr_3.65d1p1-1_all bug

NOM

       epoll - Notifications d'événements d'entrées-sorties

SYNOPSIS

       #include <sys/epoll.h>

DESCRIPTION

       L'interface  de  programmation  (API)  epoll  réalise  une tâche similaire à poll(2) : la surveillance de
       plusieurs descripteurs de fichier pour voir si les E/S y sont possibles. L'API epoll peut être déclenchée
       par niveau ou par changement d'état, et s'adapte bien à un grand nombre de descripteurs  simultanés.  Les
       appels système suivants sont fournis pour créer et superviser une instance epoll :

       *  epoll_create(2)  créé  une  instance  epoll  et  renvoie  un  descripteur de fichier référençant cette
          instance (la dernière version d'epoll_create1(2) étend les fonctionnalités d'epoll_create(2)).

       *  L'intérêt pour un descripteur de fichier est ensuite  enregistré  avec  epoll_ctl(2).  L'ensemble  des
          descripteurs  de  fichiers  actuellement  enregistrés  pour  une  instance epoll est parfois appelé un
          ensemble epoll.

       *  epoll_wait(2) attend les événements d'E/S, en bloquant le thread appelant  si  aucun  événement  n'est
          actuellement disponible.

   Détection de niveau et détection de transition
       L'interface  de  distribution  d'événements  de  epoll est capable de se comporter en détection de niveau
       (Level Triggered - LT) ou en détection de transition (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 epoll.

       2. Celui qui écrit dans le tube envoie 2 Ko de données.

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

       4. Le lecteur du tube lit 1 Ko de données depuis rfd.

       5. Un appel de epoll_wait(2) est effectué.

       Si le descripteur rfd a été ajouté à l'ensemble epoll en utilisant l'attribut  EPOLLET  (edge-triggered),
       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  les  tampons  d'entrée  du fichier et 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  Edge
       Triggered  délivre  les événements seulement lorsque des événements surviennent sur le 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  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 ne bloque, par une famine, une
       tâche qui gère plusieurs descripteurs de fichier. L'utilisation préconisée d'epoll  avec  l'interface  en
       détection de changements (EPOLLET) est la suivante :

              i   avec des descripteurs non bloquants ; et

              ii  en attendant seulement après qu'un read(2) ou un write(2) a renvoyé EAGAIN.

       Au  contraire, lorsqu'il est utilisé avec l'interface en détection 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.

       Même  dans  un  epoll de type Edge Triggered, 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.

   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  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 de epoll avec un déclenchement par niveau correspond à la  même  sémantique  que
       poll(2),  le  déclenchement  par  changement  d'état  nécessite plus d'explication pour éviter les cas de
       blocage. Dans cet exemple, le lecteur emploie une socket non  bloquante  sur  laquelle  listen(2)  a  été
       appelée.  La  fonction  do_use_fd()  va utiliser le nouveau descripteur de fichier, jusqu'à ce que EAGAIN
       soit renvoyé par read(2) ou par write(2). Une application fonctionnant  par  transition  d'état  devrait,
       après  réception  d'EAGAIN, enregistrer l'état en cours, afin que l'appel suivant de do_use_fd() continue
       avec le read(2) ou le write(2) où il s'est arrêté.

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

           /* Set up listening socket, 'listen_sock' (socket(),
              bind(), listen()) */

           epollfd = epoll_create(10);
           if (epollfd == -1) {
               perror("epoll_create");
               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_pwait");
                   exit(EXIT_FAILURE);
               }

               for (n = 0; n < nfds; ++n) {
                   if (events[n].data.fd == listen_sock) {
                       conn_sock = accept(listen_sock,
                                       (struct sockaddr *) &local, &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  epoll (EPOLL_CTL_ADD) une fois, 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
       Q0  Quelle  est  la clé utilisée pour distinguer les descripteurs de fichier enregistrés dans un ensemble
           epoll ?

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

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

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

       Q2  Deux  instances  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 epoll en même temps ?

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

       Q3  Peut-on utiliser le descripteur de epoll lui-même avec poll/epoll/select ?

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

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

       A4  L'appel  à epoll_ctl(2) échouera (EINVAL). Toutefois vous pouvez ajouter un descripteur de epoll dans
           un autre ensemble epoll.

       Q5  Puis-je envoyer le descripteur de epoll à travers une socket UNIX vers un autre processus ?

       A5  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 l'ensemble epoll.

       Q6  Est-ce que la fermeture d'un descripteur le supprime automatiquement de tous les ensembles epoll ?

       A6  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), fcntl(2) F_DUPFD 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'un ensemble epoll qu'après la fermeture de tous les descripteurs de fichier qui se réfèrent
           à la description de fichier ouvert sous-jacente (ou avant si le descripteur est explicitement  retiré
           en  utilisant epoll_ctl(2) EPOLL_CTL_DEL). Cela signifie que même après la fermeture d'un descripteur
           de fichier d'un ensemble epoll, des événements peuvent toujours être remonté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.

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

       A7  Ils sont combinés.

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

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

       Q9  Dois-je  lire/écrire  sans  cesse  un  descripteur  jusqu'à  obtenir  EAGAIN  avec l'attribut EPOLLET
           (comportement edge-triggered) ?

       A9  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.  Vous  devez  le considérer 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, une socket datagramme ou un terminal en mode
           canonique), la seule façon de détecter la fin  de  l'espace  d'entrée-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-sorties peut-être vérifiée par la quantité de données lues ou écrites  avec
           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ûrs 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 garantir que le  descripteur  de  fichier  surveillé  correspond
           toujours à un fichier de type flux)

   Erreurs possibles et moyens de les éviter
       o Famine (edge-triggered)

       S'il  y  a  un  gros  volume  d'entrées-sorties,  il est possible qu'en essayant de les traiter, d'autres
       fichiers ne soient pas pris en compte, ce  qu'on  appelle  un  cas  de  famine.  Ce  problème  n'est  pas
       spécifique à epoll.

       La  solution  est  de  maintenir  une  liste de descripteurs prêts et de les marquer comme tels dans leur
       structure associée, permettant à l'application de savoir quels fichiers traiter, en organisant l'ordre au
       mieux. Cela permet aussi d'ignorer les événements ultérieurs sur des descripteurs prêts.

       o Utilisation d'un cache d'événements...

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

       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), et marquer sa structure associée comme supprimée.
       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. La prise en charge par la glibc a été 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.

VOIR AUSSI

       epoll_create(2), epoll_create1(2), epoll_ctl(2), epoll_wait(2)

COLOPHON

       Cette page fait partie de la publication 3.65 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

       Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a <http://po4a.alioth.debian.org/> par
       l'équipe de traduction francophone au sein du projet perkamon <http://perkamon.alioth.debian.org/>.

       Christophe      Blaess      <http://www.blaess.fr/christophe/>      (1996-2003),       Alain       Portal
       <http://manpagesfr.free.fr/>  (2003-2006).  Julien  Cristau  et  l'équipe  francophone  de  traduction de
       Debian (2006-2009).

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

Linux                                             17 avril 2012                                         EPOLL(7)