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