eventfd
Section: System Calls (2)
Updated: 10 février 2023
Index
Return to Main Contents
NOM
eventfd - Créer un descripteur de fichier pour la notification d'événements
BIBLIOTHÈQUE
Bibliothèque C standard (libc, -lc)
SYNOPSIS
#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);
DESCRIPTION
eventfd() créée un « objet eventfd » qui peut être utilisé par les
applications de l'espace utilisateur pour l'attente ou la notification d'un
événement et par le noyau pour notifier des applications de certains
événements. Les objets contiennent un compteur entier non signé sur 64 bits
(uint64_t) qui est maintenu par le noyau. Ce compteur est initialisé à la
valeur spécifiée par le paramètre initval.
Comme valeur de retour, eventfd() renvoie un nouveau descripteur de
fichier qui peut être utilisé pour se référer à l'objet eventfd.
Les valeurs suivantes peuvent être incluses (avec un OU logique) dans
flags pour changer le comportement de eventfd() :
- EFD_CLOEXEC (depuis Linux 2.6.27)
-
Placer l'attribut « close-on-exec » (FD_CLOEXEC) sur le nouveau
descripteur de fichier. Consultez la description de l'attribut O_CLOEXEC
dans open(2) pour savoir pourquoi cela peut être utile.
- EFD_NONBLOCK (depuis Linux 2.6.27)
-
Placer l'attribut d'état de fichier O_NONBLOCK sur la description du
fichier ouvert référencée par le nouveau descripteur de fichier (consulter
open(2)). Utiliser cet attribut économise des appels supplémentaires à
fcntl(2) pour obtenir le même résultat.
- EFD_SEMAPHORE (depuis Linux 2.6.30)
-
Fournir une sémantique similaire aux sémaphores pour les lectures sur le
nouveau descripteur de fichier. Voir ci-dessous.
Jusqu'à Linux 2.6.26, le paramètre flags n'est pas utilisé et doit valoir
zéro.
Les opérations suivantes peuvent être effectuées sur le descripteur de
fichier renvoyé par eventfd() :
- read(2)
-
Chaque read(2) qui réussit renvoie un entier sur 8 octets. read(2)
échouera avec l'erreur EINVAL si la taille du tampon fourni est de moins
de 8 octets.
-
La valeur renvoyée par read(2) utilise l'ordre des octets de l'hôte,
c'est-à-dire l'ordre des octets natif pour les entiers sur la machine hôte.
-
La sémantique de read(2) dépend du fait que le compteur eventfd a
actuellement une valeur non nulle, et que l'attribut EFD_SEMAPHORE était
spécifié lors de la création du descripteur de fichier eventfd :
-
- •
-
Si EFD_SEMAPHORE n'était pas spécifié et si le compteur eventfd a une
valeur non nulle, un read(2) renverra 8 octets contenant cette valeur, et
la valeur du compteur sera remise à zéro.
- •
-
Si EFD_SEMAPHORE était spécifié et si le compteur eventfd a une valeur
non nulle, un read(2) renverra 8 octets contenant la valeur 1, et la
valeur du compteur sera décrémentée de 1.
- •
-
Si le compteur eventfd est nul au moment de l'appel à read(2), l'appel
bloquera jusqu'à ce que le compteur devienne non nul (auquel cas l'appel à
read(2) sera traité comme décrit ci-dessus), ou échouera avec l'erreur
EAGAIN si le descripteur de fichier est en mode non bloquant.
- write(2)
-
Un appel à write(2) ajoute au compteur la valeur de l'entier sur 8 octets
fourni dans le tampon. La valeur maximale qui peut être stockée dans le
compteur est le plus grand entier non signé sur 64 bits moins 1
(c'est-à-dire 0xfffffffffffffffe). Si l'addition résulte en un compteur qui
dépasserait la valeur maximale, le write(2) bloquera jusqu'à ce qu'un
read(2) soit effectué sur le descripteur de fichier, ou échouera avec
l'erreur EAGAIN si le descripteur de fichier est en mode non bloquant.
-
Un write(2) échouera avec l'erreur EINVAL si la taille du tampon
fourni est de moins de 8 octets ou si l'on essaie d'écrire la valeur
0xffffffffffffffff.
- poll(2), select(2) (et similaire)
-
Le descripteur de fichier prend en charge les poll(2) (et de façon
analogue epoll(7)) et select(2) de la façon suivante :
-
- •
-
Le descripteur de fichier est lisible (le paramètre readfds de
select(2) ; l'attribut POLLIN de poll(2)) si le compteur a une
valeur supérieure à 0.
- •
-
Le descripteur de fichier est disponible en écriture (le paramètre
writefds de select(2) ; l'attribut POLLOUT de poll(2)) s'il est
possible d'écrire une valeur d'au moins « 1 » sans bloquer.
- •
-
Si un dépassement de la valeur du compteur a été détectée, select(2)
indique que le descripteur de fichier est disponible en lecture et en
écriture et poll(2) renvoie un événement POLLERR. Comme indiquée
ci-dessus, un write(2) ne peut jamais produire de dépassement. Cependant,
un dépassement peut se produire si un « signal post » eventfd de 2ha64 a
été effectué par le sous-système KAIO (théoriquement possible, mais très
peut probable en pratique). Si un dépassement survient, un read(2)
renverra la valeur maximale d'un uint64_t (c'est-à-dire
0xffffffffffffffff).
-
Le descripteur de fichier eventfd prend également en charge les autres
interfaces de multiplexage de descripteurs de fichier : pselect(2) et
ppoll(2).
- close(2)
-
Quand le descripteur de fichier n'est plus nécessaire il doit être
fermé. Quand tous les descripteurs de fichier associés au même objet eventfd
ont été fermés, les ressources pour cet objet sont libérées par le noyau.
Une copie d'un descripteur de fichier créé par eventfd() est héritée par
le fils produit par fork(2). Le duplicata du descripteur de fichier est
associé au même objet eventfd. Les descripteurs de fichier créés par
eventfd() sont préservés au travers des exécutions par execve(2), sauf
si l'attribut « close-on-exec » est positionné.
VALEUR RENVOYÉE
S'il réussit, eventfd() renvoie un nouveau descripteur de fichier
eventfd. En cas d'erreur, il renvoie -1 et remplit errno avec la valeur
d'erreur.
ERREURS
- EINVAL
-
Une valeur non prise en compte a été spécifiée dans flags.
- EMFILE
-
La limite du nombre de descripteurs de fichiers par processus a été
atteinte.
- ENFILE
-
La limite du nombre total de fichiers ouverts pour le système entier a été
atteinte.
- ENODEV
-
Impossible de monter (en interne) le périphérique anonyme d'inœud.
- ENOMEM
-
Il n'y a pas assez de mémoire pour que le noyau crée le nouveau descripteur
de fichier eventfd.
VERSIONS
eventfd() est disponible depuis Linux 2.6.22. Une prise en charge
fonctionnelle est fournie depuis la glibc 2.8. L'appel système eventfd2()
(consultez les NOTES) est disponible sous Linux depuis Linux 2.6.27. Depuis
la glibc 2.9, la fonction enveloppe de la glibc pour eventfd() utilise
l'appel système eventfd2() s'il est pris en charge par le noyau.
ATTRIBUTS
Pour une explication des termes utilisés dans cette section, consulter
attributes(7).
Interface | Attribut | Valeur
|
eventfd()
| Sécurité des threads | MT-Safe
|
STANDARDS
eventfd() et eventfd2() sont spécifiques à Linux.
NOTES
Les applications peuvent utiliser un descripteur de fichier eventfd à la
place d'un tube (consultez pipe(2)) à chaque fois qu'un tube est utilisé
pour signaler des événements. La surcharge du noyau pour un descripteur de
fichier est bien plus faible que pour un tube. De plus un seul descripteur
de fichier est nécessaire (alors que deux sont nécessaires pour un tube).
Quand un descripteur de fichier eventfd est utilisé par le noyau, il peut
fournir un pont entre l'espace utilisateur et l'espace noyau. Par exemple,
les fonctionnalités comme KAIO (« kernel AIO ») pour signaler dans un
descripteur de fichier que certaines opérations sont finies.
Un aspect important d'un descripteur de fichier eventfd est qu'il peut être
surveillé comme n'importe quel descripteur de fichier avec select(2),
poll(2) ou epoll(7). Ceci signifie qu'une application peut surveiller
simultanément la disponibilité de fichiers « traditionnels » et la
disponibilité de mécanismes noyau qui gèrent une interface eventfd. (Sans
l'interface eventfd(), ces mécanismes ne pouvaient pas être multiplexés
avec select(2), poll(2) ou epoll(7))
La valeur actuelle d'un compteur eventfd peut être visualisée avec l'entrée
du descripteur de fichier correspondant dans le répertoire
/proc/pid/fdinfo du processus. Voir proc(5) pour plus de détails.
différences entre bibliothèque C et noyau
Il y a deux appels système sous-jacent : eventfd() et eventfd2(), plus
récent. Le premier appel système n'implémente pas le paramètre flags. Le
dernier appel système implémente les valeurs de flags décrite
ci-dessus. La fonction enveloppe de la glibc utilisera eventfd2() quand
il est présent.
Fonctionnalités supplémentaires de la glibc
La bibliothèque C de GNU définie un type supplémentaire et deux fonctions
qui tentent d'abstraire certains détails pour la lecture ou l'écriture avec
des descripteurs de fichier eventfd :
typedef uint64_t eventfd_t;
int eventfd_read(int fd, eventfd_t *value);
int eventfd_write(int fd, eventfd_t value);
Les fonctions effectuent des actions de lecture ou écriture sur le
descripteur de fichier eventfd, en renvoyant 0 si un nombre correct d'octets
a été transféré, ou -1 sinon.
EXEMPLES
Le programme suivant crée un descripteur de fichier eventfd puis crée un
processus fils. Alors que le père commence par s'endormir, le fils écrit
tous les entiers fournis sur la ligne de commande au descripteur de fichier
eventfd. Quand le père se réveille, il lit dans le descripteur de fichier
eventfd.
La session d'interpréteur suivant montre un échantillon d'exécution du
programme :
$ ./a.out 1 2 4 7 14
Child writing 1 to efd
Child writing 2 to efd
Child writing 4 to efd
Child writing 7 to efd
Child writing 14 to efd
Child completed write loop
Parent about to read
Parent read 28 (0x1c) from efd
Source du programme
#include <err.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/eventfd.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
int efd;
uint64_t u;
ssize_t s;
if (argc < 2) {
fprintf(stderr, "Usage: %s <num>...\n", argv[0]);
exit(EXIT_FAILURE);
}
efd = eventfd(0, 0);
if (efd == -1)
err(EXIT_FAILURE, "eventfd");
switch (fork()) {
case 0:
for (size_t j = 1; j < argc; j++) {
printf("Écriture de l'enfant %s dans efd\en", argv[j]);
u = strtoull(argv[j], NULL, 0);
/* strtoull() autorise plusieurs bases bases */
s = write(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
err(EXIT_FAILURE, }
printf("L'enfant a fini la boucle d'écriture\n");
exit(EXIT_SUCCESS);
default:
sleep(2);
printf( s = read(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
err(EXIT_FAILURE, "read");
printf("Lecture du parent %"PRIu64" (%#"PRIx64") depuis efd\n", u, u);
exit(EXIT_SUCCESS);
case -1:
err(EXIT_FAILURE, "fork");
}
}
VOIR AUSSI
futex(2), pipe(2), poll(2), read(2), select(2),
signalfd(2), timerfd_create(2), write(2), epoll(7),
sem_overview(7)
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>,
Cédric Boutillier <cedric.boutillier@gmail.com>,
Frédéric Hantrais <fhantrais@gmail.com>
et
Jean-Philippe MENGUAL <jpmengual@debian.org>
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 à
Index
- NOM
-
- BIBLIOTHÈQUE
-
- SYNOPSIS
-
- DESCRIPTION
-
- VALEUR RENVOYÉE
-
- ERREURS
-
- VERSIONS
-
- ATTRIBUTS
-
- STANDARDS
-
- NOTES
-
- différences entre bibliothèque C et noyau
-
- Fonctionnalités supplémentaires de la glibc
-
- EXEMPLES
-
- Source du programme
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 05:41:43 GMT, May 18, 2024