Man page - epoll(7)

Packages contains this manual

Available languages:

en fr ja ru zh_TW zh_CN

Manual

epoll

NOM
SYNOPSIS
DESCRIPTION
DĂ©tection par changement de niveau ou d’état
Interaction avec autosleep
/proc interfaces
Exemple d’utilisation
Questions/Réponses
Erreurs possibles et moyens de les éviter
VERSIONS
STANDARDS
HISTORIQUE
NOTES
VOIR AUSSI
TRADUCTION

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), ioctl_eventpoll (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 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 .