EVENTFD
Section : Manuel du programmeur Linux (
2)
Mise à jour de la version anglaise : 11 février 2008
Index
Menu principal
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é comme un mécanisme
d'attente/notification d'événement par les applications en espace
utilisateur et par le noyau pour notifier des événements aux applications
en espace utilisateur.
L'objet contient un compteur représenté par un entier 64 bits non signé
(
uint64_t)
qui est maintenu par le noyau.
Ce compteur est initialisé avec la valeur indiquée dans l'argument
initval.
L'argument
flags
n'est actuellement pas utilisé et doit être spécifié à zéro.
Dans le futur, il pourrait être utilisé pour demander
des fonctionnalités supplémentaires.
Comme valeur de retour,
eventfd()
renvoie un nouveau descripteur de fichier qui peut être utilisé pour faire
référence à 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,
read(2)
renvoie 8 octets contenants cette valeur et la valeur du compteur
est réinitialisée à zéro.
(La valeur renvoyée utilise l'ordre des octets de l'hôte, c'est-à-dire
l'ordre natif des octets pour les entiers sur la machine hôte.)
-
Si le compteur vaut zéro au moment de l'appel à
read(2),
l'appel bloquera jusqu'à ce que le compteur ne soit plus nul,
ou bien échouera avec l'erreur
EAGAIN
si le descripteur de fichier était en mode non bloquant
(via l'utilisation de l'opération
F_SETFL
de
fcntl(2)
pour définir l'attribut
O_NONBLOCK).
-
Un
read(2)
échouera avec l'erreur
EINVAL
si la taille du tampon fourni est inférieure à 8 octets.
- write(2)
-
Un appel à
write(2)
ajoute au compteur la valeur entière sur 8 octets fournie
dans son tampon.
La valeur maximum qui puisse être stockée dans le compteur est la plus
grande valeur 64 bits non signée moins 1
(c'est-à-dire, 0xfffffffffffffffe).
Si l'addition fait que la valeur du compteur dépasse le maximum,
l'appel à
write(2)
bloquera jusqu'à ce qu'un
read(2)
soit effectué sur le descripteur de fichier,
ou bien échouera avec l'erreur
EAGAIN
si le descripteur de fichier était en mode non bloquant.
-
Un
write(2)
échouera avec l'erreur
EINVAL
si la taille du tampon fourni est inférieure à 8 octets ou si on essaie
d'écrire la valeur 0xffffffffffffffff.
- poll(2), select(2) (et semblables)
-
Le descripteur de fichier renvoyé prend en charge
poll(2)
(et par analogie
epoll(7))
et
select(2),
de la façon suivante :
-
- *
-
Le descripteur de fichier est accessible en lecture
(l'argument
readfds
de
select(2) ;
l'attribut
POLLIN
de
poll(2))
si le compteur à une valeur supérieure à 0.
- *
-
Le descripteur de fichier est accessible en écriture
(l'argument
writefds
de
select(2) ;
l'attribut
POLLOUT
de
poll(2))
s'il est possible d'écrire une valeur d'au moins « 1 » sans bloquer.
- *
-
Le descripteur de fichier indique une condition exceptionnelle
(l'argument
exceptfds
de
select(2) ;
l'attribut
POLLERR
de
poll(2))
si un débordement du compteur est détecté.
Comme indiqué plus haut,
write(2)
ne peut jamais faire déborder le compteur.
Toutefois, un débordement peut survenir si 2^64 « envois de signaux »
eventfd étaient effectués par le sous-système KAIO (théoriquement possible,
pratiquement improbable).
Si un débordement survient,
read(2)
renverra la valeur
uint64_t
maximum (c'est-à-dire, 0xffffffffffffffff).
-
Le descripteur de fichier eventfd accepte également les autres
interface de multiplexage de descripteurs de fichier :
pselect(2),
ppoll(2),
et
epoll(7).
- close(2)
-
Lorsque le descripteur de fichier n'est plus nécessaire,
il doit être fermé.
Lorsque 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 du descripteur de fichier créé par
eventfd()
est hérité 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 à travers un
execve(2).
VALEUR RENVOYÉE
S'il réussit,
eventfd()
renvoie un nouveau descripteur de fichier eventfd.
S'il échoue, -1 est renvoyé et
errno
est renseignée en conséquence.
ERREURS
- EINVAL
-
flags
n'est pas nul.
- EMFILE
-
La limite par processus des descripteurs de fichier ouverts
a été atteinte.
- ENFILE
-
La limite à l'échelle du système du nombre total de fichiers ouverts
a été atteinte.
- ENODEV
-
Impossible de monter le périphérique anonyme inode (interne).
- ENOMEM
-
Il n'y a pas suffisamment de mémoire pour créer un nouveau descripteur
de fichiers eventfd.
VERSIONS
eventfd()
est disponible sous Linux depuis le noyau 2.6.22.
Une prise en charge fonctionnelle est fournie dans la glibc
depuis la version 2.8.
CONFORMITÉ
eventfd()
est spécifique à 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 simplement
des événements.
La surcharge du noyau (Ndt : kernel overhead) pour un descripteur de
fichier est 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).
Lorsqu'il est utilisé dans le noyau, un descripteur de fichier eventfd
peut fournir un pont entre le noyau et l'espace utilisateur permettant,
par exemple, à des fonctionnalités comme KAIO (kernel AIO)
de signaler à un descripteur de fichier que certaines opérations
sont achevées.
Un aspect important des descripteurs de fichier est qu'ils peuvent
être surveillés comme n'importe quel descripteur de fichier avec
select(2),
poll(2)
ou
epoll(7).
Cela signifie qu'une application peut surveiller simultanément
la disponibilité de fichiers « traditionnels » et la disponibilité
d'autres mécanismes du noyau qui prennent en charge l'interface eventfd.
(Sans l'interface
eventfd(),
ces mécanismes ne pourraient pas être multiplexés via
select(2),
poll(2)
ou
epoll(7).)
L'argument
flags
est un ajout de la glibc à l'appel système sous-jacent
qui ne prend que l'argument
initval.
Fonctionnalités supplémentaires de la glibc
La bibliothèque C GNU définit un type supplémentaire
et deux fonctions qui tentent d'abstraire certains détails de
lecture et d'écriture sur un descripteur 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 opérations de lecture et d'écriture
sur un descripteur de fichier, renvoyant 0 si le nombre correct d'octets
a été transféré ou -1 autrement.
EXEMPLE
Le programme suivant crée un descripteur de fichier et se clone
pour créer un processus fils.
Pendant que le parent sommeille brièvement, le fils écrit chacun
des entiers fournis dans les arguments de la ligne de commande
du programme dans le descripteur de fichier eventfd.
Lorsque le parent sort de son sommeil,
il lit le descripteur de fichier eventfd.
La session shell suivante montre un exemple de l'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
#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> /* Définition 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)
TRADUCTION
Ce document est une traduction réalisée par Alain Portal
<aportal AT univ-montp2 DOT fr> le 23 avril 2008
et révisée le 24 juin 2008.
L'équipe de traduction a fait le maximum pour réaliser une adaptation
française de qualité. La version anglaise la plus à jour de ce document est
toujours consultable via la commande : « LANG=C man 2 eventfd ».
N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute
erreur dans cette page de manuel.
Index
- NOM
-
- SYNOPSIS
-
- DESCRIPTION
-
- VALEUR RENVOYÉE
-
- ERREURS
-
- VERSIONS
-
- CONFORMITÉ
-
- NOTES
-
- Fonctionnalités supplémentaires de la glibc
-
- EXEMPLE
-
- VOIR AUSSI
-
- TRADUCTION
-
Dernière mise à jour : 24 juin 2008