TIMERFD_CREATE(2)

NOM
timerfd_create, timerfd_settime, timerfd_gettime - Temporisations qui délivrent des notifications via des descripteurs de fichier

SYNOPSIS
#include <sys/timerfd.h>

int timerfd_create(int clockid, int flags);

int timerfd_settime(int fd, int flags,
                    const struct itimerspec *new_value,
                    struct itimerspec *curr_value);

int timerfd_gettime(int fd, struct itimerspec *curr_value);

DESCRIPTION
Ces appels système créent et exploitent une temporisation qui délivre des notifications d'expiration de temporisation à travers un descripteur de fichier. Ils fournissent une alternative à l'utilisation de setitimer(2) ou timer_create(3), avec l'avantage que le descripteur de fichier peut être surveillé par select(2), poll(2) ou epoll(7). L'utilisation de ces trois appels système est analogue à l'utilisation de timer_create(3), timer_settime(3) et timer_gettime(3). (Il n'y a pas d'analogie avec timer_gettoverrun(3), puisque cette fonctionnalité est fournie par read(2), comme décrit plus loin.)

  timerfd_create()
timerfd_create() crée un nouvel objet temporisation et renvoie un descripteur de fichier qui fait référence à cette temporisation. L'argument clockid indique l'horloge qui est utilisée pour indiquer la progression de la temporisation et doit valoir soit CLOCK_REALTIME, soit CLOCK_MONOTONIC. CLOCK_REALTIME est une horloge configurable à l'échelle du système. CLOCK_MONOTONIC n'est pas configurable et n'est donc pas affectée par des modifications discontinues de l'horloge système (par exemple, par des modifications manuelles de l'heure système). La valeur actuelle de chacune de ces horloges peut être récupérée avec clock_gettime(3). L'argument flags est réservé pour une utilisation future. Dans Linux 2.6.25, cet argument doit être spécifié à zéro.

  timerfd_settime()
timerfd_settime() arme (lance) ou désarme (arrête) la temporisation référencée par le descripteur de fichier fd. L'argument new_value spécifie la date d'expiration initiale et l'intervalle de la temporisation. La structure itimer utilisée pour cet argument contient deux champs, chacun d'entre eux étant une structure de type timespec :
struct timespec {
    time_t tv_sec;                /* Secondes */
    long   tv_nsec;               /* Nanosecondes */
};
struct itimerspec {
    struct timespec it_interval;  /* Intervalle pour les temporisations périodiques */
    struct timespec it_value;     /* Expiration initiale */
};

new_value.it_value spécifie la date d'expiration initiale de la temporisation, en secondes et nanosecondes. Définir l'un des champs de new_value.it_value avec une valeur non nulle arme la temporisation. Définir les deux champs de new_value.it_value à zéro désarme la temporisation. Définir un ou les deux champs de new_value.it_interval à une valeur non nulle spécifie la période, en secondes et nanosecondes, pour des expirations de la temporisation répétitives après la première expiration. Si les deux champs de new_value.it_interval sont nuls, la temporisation expire une seule fois, à la date indiquée par new_value.it_value. L'argument flags est soit 0, pour lancer une temporisation relative (new_value.it_interval spécifie un temps relatif par rapport à la valeur actuelle de l'horloge indiquée par clockid), soit TFD_TIMER_ABSTIME, pour lancer une temporisation absolue (new_value.it_interval spécifie un temps absolu pour l'horloge spécifiée par clockid ; ainsi, la temporisation expirera lorsque la valeur de cette horloge atteindra la valeur spécifiée dans new_value.it_interval). L'argument curr_value renvoie une structure contenant la configuration en cours de la temporisation au moment de l'appel ; voir la description de timerfd_gettime().

  timerfd_gettime()
timerfd_gettime() renvoie dans curr_value une structure itimerspec qui contient la configuration actuelle de la temporisation référencée par le descripteur de fichier fd. Le champ it_value renvoie le temps restant jusqu'à la prochaine expiration de la temporisation. Si les deux champs de cette structure sont nuls, la temporisation est actuellement désarmée. Ce champ contient toujours une valeur relative, que l'attribut TFD_TIMER_ABSTIME ait été spécifié ou non lors de la configuration de la temporisation. Le champ it_interval renvoie la période de la temporisation. Si les deux champs de cette structure sont nuls, la temporisation a été configurée pour n'expirer qu'une seule fois, à la date spécifiée par curr_value.it_value.

  Opérations sur un descripteur de fichier temporisation
Le descripteur de fichier renvoyé par timerfd_create() accepte les opérations suivantes :

read(2)
    Si la temporisation a déjà expiré une ou plusieurs fois depuis que sa configuration a été modifiée avec timerfd_settime(), ou depuis le dernier appel réussi à read(2), alors le tampon fourni à read(2) renvoie un entier non signé sur 8 octets (uint64_t) contenant le nombre d'expirations qui se sont produites. (La valeur renvoyée est dans l'odre d'octet de l'hôte, c'est-à-dire l'ordre natif d'octet pour les entiers sur la machine hôte.)

    Si aucune expiration ne s'est produite au moment du read(2), l'appel soit bloquera jusqu'à la prochaine expiration de la temporisation, soit échouera avec l'erreur EAGAIN si le descripteur de fichier a été rendu 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.

poll(2), select(2) (et similaires)
    Le descripteur de fichier est accessible en lecture (l'argument readfds de select(2) ; l'attribut POLLIN de poll(2)) si une ou plusieurs expirations se sont produites.

    Le descripteur de fichier accepte également les autres API de multiplexage de descripteur 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 temporisation ont été fermés, la temporisation est désarmée et ses ressources sont libérées par le noyau.

  Sémantique de fork(2)
Après un fork(2), le fils hérite d'une copie du descripteur de fichier créé par timerfd_create(). Le descripteur de fichier fait référence au même objet temporisation sous-jacent que le descripteur de fichier correspondant dans le parent, et les read(2) dans le fils renverront les informations relatives aux expirations de la temporisation.

  Sémantique de execve(2)
Un descripteur de fichier créé avec timerfd_create() est préservé à travers un execve(2), et continue à générer des expirations de temporisation si celle-ci était armée.

VALEUR RENVOYÉE
S'il réussit, timerfd_create() renvoie un nouveau descripteur de fichier. S'il échoue, -1 est renvoyé auquel cas errno contient le code d'erreur. timerfd_settime() et timerfd_gettime() renvoient 0 s'ils réussissent ; s'ils échouent, ils renvoient -1 et définissent errno pour indiquer l'erreur.

ERREURS
timerfd_create() peut échouer avec les erreurs suivantes :

EINVAL
    L'argument clockid n'est ni CLOCK_MONOTONIC, ni CLOCK_REALTIME ; ou flags n'est pas valide.

EMFILE
    La limite par processus du nombre total de descripteurs de fichier ouverts a été atteinte.

ENFILE
    La limite du nombre total de fichier ouverts sur le système a été atteinte.

ENODEV
    Impossible de monter le périphérique anonyme d'inœud (interne).

ENOMEM
    Il n'y a pas suffisamment de mémoire noyau pour créer la temporisation.

timerfd_settime() et timerfd_gettime() peuvent échouer avec les erreurs suivantes :

EBADF
    fd n'est pas un descripteur de fichier valide.

EINVAL
    fd n'est pas un descripteur de fichier timerfd valide. new_value n'est pas correctement initialisé (un des champs tv_nsec est hors de l'intervalle 0 à 999 999 999).

VERSIONS
Ces appels système sont disponibles sous Linux depuis le noyau 2.6.25. La prise en charge par la bibliothèque glibc est fournie depuis la version 2.8.

CONFORMITÉ
Ces appels système sont spécifiques à Linux.

EXEMPLE
Le programme suivant crée une temporisation et surveille sa progression. Le programme accepte jusqu'à trois arguments sur sa ligne de commande. Le premier argument spécifie le nombre de secondes pour l'expiration initiale de la temporisation. Le deuxième argument spécifie l'intervalle, en secondes, de la temporisation. Le troisième argument spécifie le nombre de fois que le programme autorise la temporisation à expirer avant de se terminer Les deuxième et troisième argument de la ligne de commande sont facultatifs. La session shell suivante montre l'utilisation du programme :
$ a.out 3 1 100
0.000: timer started
3.000: read: 1; total=1
4.000: read: 1; total=2
[type control-Z to suspend the program]
[1]+  Stopped                 ./timerfd3_demo 3 1 100
$ fg                # Resume execution after a few seconds
a.out 3 1 100
9.660: read: 5; total=7
10.000: read: 1; total=8
11.000: read: 1; total=9
[type control-C to terminate the program]
#include <sys/timerfd.h>
#include <time.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)
static void
print_elapsed_time(void)
{
    static struct timespec start;
    struct timespec curr;
    static int first_call = 1;
    int secs, nsecs;
    if (first_call) {
        first_call = 0;
        if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
            handle_error("clock_gettime");
    }
    if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)
        handle_error("clock_gettime");
    secs = curr.tv_sec - start.tv_sec;
    nsecs = curr.tv_nsec - start.tv_nsec;
    if (nsecs < 0) {
        secs--;
        nsecs += 1000000000;
    }
    printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);
}
int
main(int argc, char *argv[])
{
    struct itimerspec new_value;
    int max_exp, fd;
    struct timespec now;
    uint64_t exp, tot_exp;
    ssize_t s;
    if ((argc != 2) && (argc != 4)) {
        fprintf(stderr, "%s init-secs [interval-secs max-exp]\n",
                argv[0]);
        exit(EXIT_FAILURE);
    }
    if (clock_gettime(CLOCK_REALTIME, &now) == -1)
        handle_error("clock_gettime");
    /* Create a CLOCK_REALTIME absolute timer with initial
       expiration and interval as specified in command line */
    new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]);
    new_value.it_value.tv_nsec = now.tv_nsec;
    if (argc == 2) {
        new_value.it_interval.tv_sec = 0;
        max_exp = 1;
    } else {
        new_value.it_interval.tv_sec = atoi(argv[2]);
        max_exp = atoi(argv[3]);
    }
    new_value.it_interval.tv_nsec = 0;
    fd = timerfd_create(CLOCK_REALTIME, 0);
    if (fd == -1)
        handle_error("timerfd_create");
    if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
        handle_error("timerfd_settime");
    print_elapsed_time();
    printf("timer started\n");
    for (tot_exp = 0; tot_exp < max_exp;) {
        s = read(fd, &exp, sizeof(uint64_t));
        if (s != sizeof(uint64_t))
            handle_error("read");
        tot_exp += exp;
        print_elapsed_time();
        printf("read: %llu; total=%llu\n",
                (unsigned long long) exp,
                (unsigned long long) tot_exp);
    }
    exit(EXIT_SUCCESS);
}

VOIR AUSSI
eventfd(2), poll(2), read(2), select(2), setitimer(2), signalfd(2), timer_create(3), timer_gettime(3), timer_settime(3), epoll(7), time(7)

TRADUCTION

Ce document est une traduction réalisée par Alain Portal <aportal AT univ-montp2 DOT fr> le 24 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 timerfd_create ». N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute erreur dans cette page de manuel.