Provided by:
manpages-fr_3.32d0.2p4-1_all 
NOM
epoll - Notifications d'evenements d'entrees-sorties
SYNOPSIS
#include <sys/epoll.h>
DESCRIPTION
epoll est une variante de poll(2) que l'on peut declencher par niveau
ou par changement d'etat, et monte bien en charge pour un grand nombre
de descripteurs simultanes. Les appels systeme suivants sont fournis
pour creer et superviser une instance epoll :
* Une instance epoll creee par epoll_create(2), qui renvoie un
descripteur de fichier referencant l'instance epoll (la version plus
recente epoll_create1(2) etend les fonctionnalites de
epoll_create(2)).
* L'interet pour un descripteur de fichier est ensuite enregistre avec
epoll_ctl(2). L'ensemble des descripteurs de fichiers actuellement
enregistres pour une instance epoll est parfois appele un ensemble
epoll.
* Enfin, l'attente est effectivement demarree avec epoll_wait(2).
D'etection de niveau et d'etection de transition
L'interface de distribution d'evenements de epoll est capable de se
comporter en detection de niveau (Level Triggered - LT) ou en detection
de transition (Edge Triggered - ET). La difference entre ces deux
mecanismes est decrite ci-dessous. Supposons que le scenario suivant se
produise :
1. Le descripteur de fichier qui represente le cote lecture d'un tube
(rfd) est enregistre dans l'instance epoll.
2. Celui qui ecrit dans le tube envoie 2 Ko de donnees.
3. Un appel a epoll_wait(2) est effectue et renvoie rfd comme
descripteur de fichier pret.
4. Le lecteur du tube lit 1 Ko de donnees depuis rfd.
5. Un appel de epoll_wait(2) est effectue.
Si le descripteur rfd a ete ajoute a l'ensemble epoll en utilisant
l'attribut EPOLLET (edge-triggered), l'appel epoll_wait(2), realise a
l'etape 5, va probablement bloquer bien qu'il y ait des donnees
toujours presentes dans les tampons d'entree du fichier et le pair
distant attendra une reponse basee sur les donnees qu'il a deja
envoyees. La raison en est que le mecanisme de distribution
d'evenements Edge Triggered delivre les evenements seulement lorsque
des evenements surviennent sur le fichier supervise. Ainsi, a l'etape
5, l'appelant peut attendre des donnees qui sont deja presentes dans le
tampon d'entree. Dans l'exemple ci-dessus, un evenement sur rfd sera
declenche a cause de l'ecriture a l'etape 2, et l'evenement est
consomme dans 3. Comme l'operation de lecture de l'etape 4 ne consomme
pas toutes les donnees du tampon, l'appel a epoll_wait(2) effectue a
l'etape 5 peut verrouiller indefiniment.
Une application qui emploie l'attribut EPOLLET de la fonction epoll
devrait toujours utiliser des descripteurs non bloquants pour eviter
qu'une lecture ou une ecriture ne bloque, par une famine, une tache qui
gere plusieurs descripteurs de fichier. L'utilisation preconisee
d'epoll avec l'interface en detection de changements (EPOLLET) est la
suivante :
i avec des descripteurs non bloquants ; et
ii en attendant seulement apres qu'un read(2) ou un write(2) a
renvoye EAGAIN.
Au contraire, lorsqu'il est utilise avec l'interface en detection de
niveau (par defaut si EPOLLET n'est pas specifie), epoll est une
alternative plus rapide a poll(2), et peut etre employe chaque fois que
ce dernier est utilise, car il utilise la meme semantique.
Meme dans un epoll de type Edge Triggered, plusieurs evenements peuvent
etre generes a la reception de nombreux blocs de donnees. L'appelant
peut, en specifiant l'attribut EPOLLONESHOT, faire desactiver par epoll
le descripteur de fichier associe, apres la reception d'un evenement
avec epoll_wait(2). Lorsque l'attribut EPOLLONESHOT est specifie, il
est de la responsabilite de l'appelant de rearmer le descripteur en
utilisant epoll_ctl(2) avec EPOLL_CTL_MOD.
Interfaces /proc
Les interfaces suivantes peuvent etre utilisees pour limiter la
quantite de memoire du noyau utilisee par epoll :
/proc/sys/fs/epoll/max_user_watches (depuis Linux 2.6.28)
Ceci definit une limite au nombre total de descripteurs de
fichiers qu'un utilisateur peut enregistrer au travers de toutes
les instances epoll du systeme. La limite est imposee par
identifiant d'utilisateur reel. Chaque descripteur de fichier
enregistre coute environ 90 octets sur un noyau 32 bits et
environ 160 octets sur un noyau 64 bits. Actuellement la valeur
par defaut pour max_user_watches est de 1/25 (4%) de la memoire
basse disponible, divise par le cout d'allocation en octets.
Exemple d'utilisation
Tandis que l'utilisation de epoll avec un declenchement par niveau
correspond a la meme semantique que poll(2), le declenchement par
changement d'etat necessite plus d'explication pour eviter les cas de
blocage. Dans cet exemple, le lecteur emploie une socket non bloquante
sur laquelle listen(2) a ete appelee. La fonction do_use_fd() va
utiliser le nouveau descripteur de fichier, jusqu'a ce que EAGAIN soit
renvoye par read(2) ou par write(2). Une application fonctionnant par
transition d'etat devrait, apres reception d'EAGAIN, enregistrer l'etat
en cours, afin que l'appel suivant de do_use_fd() continue avec le
read(2) ou le write(2) ou il s'est arrete.
#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 detection de changement d'etats, pour des raisons
de performances, il est possible d'ajouter le descripteur de fichier
dans l'interface epoll (EPOLL_CTL_ADD) une fois, en specifiant
(EPOLLIN|EPOLLOUT). Ceci evite de basculer sans cesse entre EPOLLIN et
EPOLLOUT lors des appels epoll_ctl(2) avec EPOLL_CTL_MOD.
Questions/R'eponses
Q0 Quelle est la cle utilisee pour distinguer les descripteurs de
fichier enregistres dans un ensemble epoll ?
A0 La cle est une combinaison du numero du descripteur de fichier et
de la description du fichier ouvert (aussi connue comme << open
file handle >>, la representation interne au noyau d'un fichier
ouvert).
Q1 Que se passe-t-il si on enregistre deux fois le meme 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 meme instance epoll. Ceci peut etre une technique
utile pour le filtrage d'evenements, si les descripteurs duplicats
sont enregistres avec un masque d'evenements events different.
Q2 Deux instances epoll peuvent-elles attendre le meme descripteur de
fichier ? Si oui, les evenements seront-ils reportes sur les deux
descripteurs de fichier epoll en meme temps ?
A2 Oui, et les evenements seront rapportes aux deux. Toutefois, une
programmation soignee est necessaire pour que cela soit fait
correctement.
Q3 Peut-on utiliser le descripteur de epoll lui-meme avec
poll/epoll/select ?
A3 Oui. Si un descripteur de fichier epoll a des evenements en
attente, alors il indiquera qu'il est lisible.
Q4 Que se passe-t-il si on cherche a placer un descripteur de epoll
dans son propre ensemble ?
A4 L'appel a epoll_ctl(2) echouera (EINVAL). Toutefois vous pouvez
ajouter un descripteur de epoll dans un autre ensemble epoll.
Q5 Puis-je envoyer le descripteur de epoll a travers une socket UNIX
vers un autre processus ?
A5 Oui, mais il n'y a aucune raison de faire ca, puisque le processus
recepteur 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 reference vers la description d'un fichier ouvert
(consultez open(2)). A chaque fois qu'un descripteur est duplique
avec dup(2), dup2(2), fcntl(2) F_DUPFD ou fork(2), un nouveau
descripteur de fichier qui se refere au meme fichier ouvert est
cree. Une description de fichier ouvert continue d'exister jusqu'a
ce que tous les descripteurs de fichier qui s'y referent soient
fermes. Un descripteur de fichier n'est retire d'un ensemble epoll
qu'apres la fermeture de tous les descripteurs de fichier qui se
referent a la description de fichier ouvert sous-jacente (ou avant
si le descripteur est explicitement retire en utilisant
epoll_ctl(2) EPOLL_CTL_DEL). Cela signifie que meme apres la
fermeture d'un descripteur de fichier d'un ensemble epoll, des
evenements peuvent toujours etre remontes pour ce descripteur de
fichier si d'autres descripteurs de fichier, se referant a la meme
description de fichier sous-jacente, restent ouverts.
Q7 Si plus d'un evenement surviennent entre deux appels epoll_wait(2),
sont-ils combines ou rapportes separement ?
A7 Ils sont combines.
Q8 Est-ce qu'une operation sur un descripteur affecte les evenements
deja collectes mais pas encore rapportes ?
A8 Vous pouvez faire deux choses sur un descripteur existant. Une
suppression serait sans signification dans ce cas. Une modification
reverifie les entrees-sorties disponibles.
Q9 Dois-je lire/ecrire sans cesse un descripteur jusqu'a obtenir
EAGAIN avec l'attribut EPOLLET (comportement edge-triggered) ?
A9 La reception d'un evenement depuis epoll_wait(2) suggere qu'un
descripteur est pret pour l'operation d'E/S desiree. Vous devez le
considerer pret jusqu'a ce que la prochaine lecture ou ecriture
(non bloquante) remonte un EAGAIN. Quand et comment utiliser le
descripteur depend de vous.
Pour les fichiers orientes paquet ou jeton (par exemple, une socket
datagramme ou un terminal en mode canonique), la seule facon de
detecter la fin de l'espace d'entree-sortie pour les lectures ou
ecritures est de continuer a lire ou ecrire jusqu'a la reception
d'un EAGAIN.
Pour les fichiers orientes flux (par exemple, les tubes, FIFO ou
sockets en mode flux), la disponibilite des entrees-sorties
peut-etre verifiee par la quantite de donnees lues ou ecrites avec
le descripteur. Par exemple, si vous appelez read(2) en demandant
la lecture d'une certaine quantite de donnees et que read(2) en
renvoie moins, vous pouvez etre surs d'avoir consomme tout le
tampon d'entree pour le descripteur. La meme chose est vraie pour
l'appel systeme write(2). (Evitez cette derniere technique si vous
ne pouvez garantir que le descripteur de fichier surveille
correspond toujours a un fichier de type flux)
Erreurs possibles et moyens de les 'eviter
o Famine (edge-triggered)
S'il y a un gros volume d'entrees-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 probleme n'est pas
specifique a epoll.
La solution est de maintenir une liste de descripteurs prets et de les
marquer comme tels dans leur structure associee, permettant a
l'application de savoir quels fichiers traiter, en organisant l'ordre
au mieux. Ceci permet aussi d'ignorer les evenements ulterieurs sur des
descripteurs prets.
o Utilisation d'un cache d''ev'enements...
Si vous utilisez un cache d'evenement, ou stockez tous les descripteurs
renvoyes par epoll_wait(2), alors assurez-vous de disposer d'un moyen
de marquer dynamiquement leurs fermetures (causees par un evenement
precedent). Supposons que vous recevez 100 evenements de epoll_wait(2),
et que l'evenement 47 implique de fermer le descripteur 13. Si vous
supprimez la structure et utilisez close(2), alors votre cache peut
encore contenir des evenements pour ce descripteur, et poser des
problemes de coherence.
Une solution est d'invoquer, pendant le traitement de l'evenement 47,
epoll_ctl(EPOLL_CTL_DEL) pour supprimer le descripteur 13, le fermer
avec close(2), et marquer sa structure associee comme supprimee. Si
vous rencontrez un autre evenement pour le descripteur 13 dans votre
traitement, vous verrez qu'il a ete supprime precedemment, sans que
cela ne prete a confusion.
VERSIONS
L'API epoll a ete introduite dans le noyau Linux 2.5.44. La prise en
charge par la glibc a ete ajoutee dans la version 2.3.2.
CONFORMIT'E
L'API epoll est specifique a Linux. Certains autres systemes
fournissent des mecanismes 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 etre trouvees a l'adresse
<URL:http://www.kernel.org/doc/man-pages/>.
TRADUCTION
Depuis 2010, cette traduction est maintenue a l'aide de l'outil po4a
<URL:http://po4a.alioth.debian.org/> par l'equipe 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'equipe francophone de traduction de Debian (2006-2009).
Veuillez signaler toute erreur de traduction en ecrivant a
<debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
paquet manpages-fr.
Vous pouvez toujours avoir acces a la version anglaise de ce document
en utilisant la commande << man -L C <section> <page_de_man> >>.
Linux 1er fevrier 2009 EPOLL(7)