NOM¶
eventfd - Créer un descripteur de fichier pour la notification
d'événements
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.
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 le nouveau descripteur de fichier ouvert. 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.
Dans les versions de Linux jusqu'à la version 2.6.26, le paramètre
flags n'est pas utilisé et doit valoir zéro.
Comme valeur de retour,
eventfd() renvoie un nouveau descripteur de
fichier qui peut être utilisé pour se référer à
l'objet eventfd. Les opérations suivantes peuvent être
effectuées sur le descripteur de fichier :
- 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 similaires)
- 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 2^64 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), ppoll(2) et epoll(7).
- 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 des descripteurs ouverts pour le processus a
été atteinte.
- ENFILE
- La limite du nombre total de fichiers ouverts sur le
système 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 sous Linux depuis le noyau 2.6.22. Le
support fonctionnel est fourni par la glibc depuis la version 2.8. L'appel
système
eventfd2() (consultez les NOTES) est disponible sous Linux
depuis le noyau 2.6.27. Depuis la version 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.
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))
Appels système Linux sous-jacents¶
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.
EXEMPLE¶
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 shell suivante montre un exemple 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 <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> /* Definition de uint64_t */
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{
int efd, j;
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)
handle_error("eventfd");
switch (fork()) {
case 0:
for (j = 1; j < argc; j++) {
printf("Child writing %s to efd\n", argv[j]);
u = strtoull(argv[j], NULL, 0);
/* strtoull() allows various bases */
s = write(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("write");
}
printf("Child completed write loop\n");
exit(EXIT_SUCCESS);
default:
sleep(2);
printf("Parent about to read\n");
s = read(efd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
handle_error("read");
printf("Parent read %llu (0x%llx) from efd\n",
(unsigned long long) u, (unsigned long long) u);
exit(EXIT_SUCCESS);
case -1:
handle_error("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)
COLOPHON¶
Cette page fait partie de la publication 3.44 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/>.
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> ».