Provided by: manpages-fr_3.32d0.2p4-1_all bug

NOM

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

SYNOPSIS

       #include <sys/epoll.h>

DESCRIPTION

       epoll  est  une  variante de poll(2) que l'on peut déclencher par niveau ou par changement
       d'état, et monte bien en charge pour un  grand  nombre  de  descripteurs  simultanés.  Les
       appels système suivants sont fournis pour créer et superviser une instance epoll :

       *  Une  instance  epoll  créée  par epoll_create(2), qui renvoie un descripteur de fichier
          référençant l'instance epoll  (la  version  plus  récente  epoll_create1(2)  étend  les
          fonctionnalités de 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.

       *  Enfin, l'attente est effectivement démarrée avec epoll_wait(2).

   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)
              Ceci  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).  Ceci  é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. Ceci  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. Ceci 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.32 du projet man-pages Linux.  Une  description
       du  projet  et  des  instructions  pour  signaler  des  anomalies  peuvent être trouvées à
       l'adresse <URL:http://www.kernel.org/doc/man-pages/>.

TRADUCTION

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

       Christophe  Blaess  <URL:http://www.blaess.fr/christophe/>   (1996-2003),   Alain   Portal
       <URL: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> ».