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);
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.
À partir de Linux 2.6.27, les valeurs suivantes peuvent être inclues
(avec un OU logique) dans flags pour changer le comportement de
eventfd() :
EFD_NONBLOCK Définir l’attribut d’état de fichier O_NONBLOCK sur le
nouveau descripteur de fichier ouvert. Utiliser cet
attribut économise des appels à fcntl(2) qui permettrait
d’obtenir le même résultat.
EFD_CLOEXEC Définir 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 quand ça
peut être utile.
Dans les versions de Linux jusqu’à la version 2.6.26, le paramètre
flags n’est pas utilisé et doit avoir la valeur 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)
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. (La valeur renvoyée 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)
Si le compteur est nul au moment du read(2), l’appel bloquera
jusqu’à ce que le compteur devienne non nul, ou échouera avec
l’erreur EAGAIN si le descripteur de fichier est en mode non
bloquant.
Un read(2) échouera avec l’erreur EINVAL si la taille du tampon
fourni est de moins de 8 octets.
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).
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 flags n’est pas correct ; ou, pour les versions de Linux 2.6.26
ou ultérieures, flags n’est pas nul.
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’inoeud.
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() (voir 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.
CONFORMITÉ
eventfd() et eventfd2() sont spécifiques à Linux.
NOTES
Les applications peuvent utiliser un descripteur de fichier eventfd à
la place d’un tube (voir 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.23 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
Cette page de manuel a été traduite et est maintenue par Julien Cristau
<julien.cristau@ens-lyon.org> et l’équipe francophone de traduction de
Debian.
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> ».