|
|||||||
|
|
EPOLLSection: Manuel du programmeur Linux (4)Updated: 25 juillet 2003 Index Return to Main Contents NOMepoll - Notifications d'évènements d'entrées/sorties.SYNOPSIS#include <sys/epoll.h>DESCRIPTIONepoll est une variante de poll(2) que l'on peut déclencher par niveau ou par changement d'état, et s'adapte bien pour un grand nombre de descripteurs simultanés. Trois appels-système sont fournis pour configurer et commander un ensemble epoll : epoll_create(2), epoll_ctl(2), epoll_wait(2).Un ensemble epoll est connecté à un descripteur de fichiers créé par epoll_create(2). L'interêt pour certains descripteurs est ensuite enregistré avec epoll_ctl(2). Enfin, l'attente effective démarre avec l'appel epoll_wait(2). NOTESL'interfac de distribution d'évènement de epoll est capable de se comporter en détection de niveau (Level Triggered - LT) ou en détection de changement d'état (Edge Triggered - ET). La différence entre ces mécanismes est décrite ci-dessous. Supposons que le scénario suivant se produise :
Si le descripteur fd_lect a été ajouté à l'ensemble epoll en utilisant l'attribut EPOLLET, l'appel epoll_wait(2) réalisé à l'étape 5 va bloquer malgré les données déjà présentes dans les buffers d'entrée du fichier. La raison en est que le mécanisme ET détecte les changements sur un périphérique supervisé entre l'état "aucune entrée/sortie possible" (0) et l'état "entrée/sortie possible" (1). Dans l'exemple ci-dessus, un événement sur fd_lect sera déclenché (en supposant que le buffer était vide à l'origine) à 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 buffer (la condition "Entrées/sorties possibles" persiste), aucune transition 0 -> 1 ne peut se produire en 5. Lorsqu'on emploie l'attribut EPOLLET (Edge Triggered) de la fonction epoll, on devrait toujours utiliser des descripteurs non-bloquants pour éviter qu'une lecture ou une écriture bloque une tâche qui gère plusieurs descripteurs de fichiers. L'utilisation suggérée d epoll avec l'interface en détection de changements (EPOLLET) est décrite ci-dessous, avec les pièges à éviter.
Au contraire, lorsqu'il est utilisé avec l'interface en détection de niveau epoll est une alternative plus rapide à poll(2), et peut être employé chaque fois que poll() est utilisé, car il utilise la même sémantique. EXEMPLE D'UTILISATION CONSEILLÉETandis 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é.
struct epoll_event ev, *events;
for(;;) {
nfds = epoll_wait(kdpfd, events, maxevents, -1);
for(n = 0; n < nfds; ++n) {
if(events[n].data.fd == listener) {
client = accept(listener, (struct sockaddr *) &local,
&addrlen);
if(client < 0){
perror("accept");
continue;
}
setnonblocking(client);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = client;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {
fprintf(stderr, "epoll set insertion error: fd=%d,
client);
return -1;
}
}
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 descriptuer 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 ET REPONSES (de la liste linux-kernel)
PIÈGES POSSIBLES, ET SOLUTIONS
Il est possible que durant une lecture (en supposant que vous lisez en boucle en attendant EAGAIN), des données supplémentaires arrivent en second événement. Bien que ces données soient lues tout de suite, l'appel suivant de epoll_wait(2) sur le descripteur dira qu'il y a un événement "lecture possible" alors qu'il a déjà été cosommé.
Dans le cas de descripteurs non-bloquants, cela fera échouer immédiatement la lecture suivante avec l'erreur EAGAIN. Dans le cas de descripteurs bloquants, on restera en attente pour lire des données non encore présentes. L'auteur recommande de ne pas utiliser de descripteur bloquant avec le mécanisme de détection de changement d'état (ET). Pour traiter ce cas, une possibilité est de marquer le descripteur comme prêt dans sa structure de données associée après la réception du premier événement, puis d'ignorer les événements tant qu'il est dans l'état prêt. Lorsque vous lisez jusqu'à recevoir EAGAIN, effacez le bit d'état prêt avant de rappeler epoll_wait(2) sur ce descripteur.
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 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énments ultérieurs sur un descripteur prêt.
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(), 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, 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édement, sans que cela ne prête à confusion. CONFORMITÉepoll(4) est une API introduie dans Linux 2.5.44. Son interface devrait être finalisée depuis le 2.5.66.VOIR AUSSIepoll_ctl(2), epoll_create(2), epoll_wait(2)TRADUCTIONChristophe Blaess, 2003
Index
| ||||||
|
|
|
Home :: Copyright :: Privacy :: Credits :: Get a free Linuxinfor Email Account Document on this page is part of "Linuxinfor Man Pages in HTML Format: man4". See Index Page for more info about Authorship and Copyright. 1999-2008 Linuxinfor.com. No rights reserved. |