Provided by: manpages-fr_3.57d1p1-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.57 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> ».