timerfd_create
Section: System Calls (2)
Updated: 5 février 2023
Index
Return to Main Contents
NOM
timerfd_create, timerfd_settime, timerfd_gettime - Minuteries qui informent
par l'intermédiaire de descripteurs de fichier
BIBLIOTHÈQUE
Bibliothèque C standard (libc, -lc)
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 *_Nullable old_value);
int timerfd_gettime(int fd, struct itimerspec *curr_value);
DESCRIPTION
Ces appels système créent et opèrent sur une minuterie qui fournit des
notifications d'expiration par un descripteur de fichier. Ils fournissent
une alternative à setitimer(2) ou timer_create(2) avec l'avantage que
le descripteur de fichier peut être surveillé avec select(2), poll(2)
ou epoll(7).
L'utilisation de ces trois appels système est analogue à l'utilisation de
timer_create(2), timer_settime(2) et timer_gettime(2). (Il n'y a
pas d'équivalent à timer_getoverrun(2) puisque cette fonctionnalité est
fournie par read(2), comme décrit ci-dessous)
timerfd_create()
timerfd_create() crée un nouvel objet minuterie et renvoie un descripteur
de fichier qui se réfère à cette minuterie. Le paramètre clockid indique
l'horloge utilisée pour marquer la progression de la minuterie qui doit être
une des suivantes :
- CLOCK_REALTIME
-
Une horloge temps réel configurable à l'échelle du système.
- CLOCK_MONOTONIC
-
Une horloge non configurable, toujours croissante qui mesure le temps depuis
un instant non spécifié dans le passé et qui ne change pas après le
démarrage du système.
- CLOCK_BOOTTIME (depuis Linux 3.15)
-
C'est une horloge toujours croissante comme CLOCK_MONOTONIC. Cependant
alors que l'horloge CLOCK_MONOTONIC ne mesure pas le temps aussi
longtemps que le système est suspendu, l'horloge CLOCK_BOOTTIME inclut le
temps pendant lequel le système est suspendu. Cela est utile pour les
applications qui doivent être sensibles au temps de
suspension. CLOCK_REALTIME n'est pas adapté à ce type d'application dans
la mesure où cette horloge est affectée par des modifications discontinues
de l'horloge système.
- CLOCK_REALTIME_ALARM (depuis Linux 3.11)
-
Cette horloge se comporte comme CLOCK_REALTIME, mais réveillera le
système s'il est suspendu. L'appelant doit avoir la capacité
CAP_WAKE_ALARM afin de régler une minuterie utilisant cette horloge.
- CLOCK_BOOTTIME_ALARM (depuis Linux 3.11)
-
Cette horloge se comporte comme CLOCK_BOOTTIME, mais réveillera le
système s'il est suspendu. L'appelant doit avoir la capacité
CAP_WAKE_ALARM afin de régler une minuterie utilisant cette horloge.
Consultez clock_getres(2) pour quelques détails supplémentaires sur les
horloges mentionnées.
La valeur actuelle de chacune de ces horloges peut être obtenue avec
clock_gettime(2).
À partir de Linux 2.6.27, les valeurs suivantes peuvent être incluses avec
un OU binaire dans flags pour changer le comportement de
timerfd_create() :
- TFD_NONBLOCK
-
Placer l'attribut d'état de fichier O_NONBLOCK sur la description du
fichier ouvert référencée par le nouveau descripteur de fichier (consulter
open(2)). Utiliser cet attribut économise des appels supplémentaires à
fcntl(2) pour obtenir le même résultat.
- TFD_CLOEXEC
-
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.
Dans les versions de Linux jusqu'à la version 2.6.26 incluse, flags doit
être nul.
timerfd_settime()
timerfd_settime() arme (démarre) ou désarme (stoppe) la minuterie à
laquelle se réfère le descripteur de fichier fd.
Le paramètre new_value spécifie l'expiration initiale et l'intervalle de
la minuterie. La structure itimerspec utilisée pour ce paramètre est
décrite dans itimerspec(3type) :
new_value.it_value spécifie l'expiration initiale de la minuterie, en
secondes et nanosecondes. Une valeur non nulle dans un des champs de
new_value.it_value arme la minuterie. La minuterie est désarmée si les
deux champs de new_value.it_value sont mis à zéro.
Une valeur non nulle dans un des champs de new_value.it_interval
configure la période, en secondes et nanosecondes, pour une expiration
répétitive après l'expiration initiale. Si les deux champs de
new_value.it_interval sont nuls, la minuterie expirera qu'une seule fois,
dont l'heure est spécifiée dans new_value.it_value.
Par défaut, l'heure d'expiration initiale spécifiée dans new_value est
interprétée de façon relative par rapport à l'heure actuelle sur l'horloge
de la minuterie au moment de l'appel (c'est-à-dire que new_value.it_value
indique une heure relative à la valeur actuelle de l'horloge spécifiée par
clockid). Un délai absolu peut être sélectionné avec le paramètre
flags.
Le paramètre flags est un masque de bits qui peut avoir les valeurs
suivantes :
- TFD_TIMER_ABSTIME
-
Interpréter new_value.it_value comme une valeur absolue sur l'horloge de
la minuterie. La minuterie expirera quand la valeur de l'horloge de la
minuterie atteint la valeur spécifiée dans new_value.it_value.
- TFD_TIMER_CANCEL_ON_SET
-
Si cet attribut est spécifié en même temps que TFD_TIMER_ABSTIME et si
l'horloge pour cette minuterie est CLOCK_REALTIME ou
CLOCK_REALTIME_ALARM, alors marquer cette minuterie comme annulable si
l'horloge en temps réel subit une modification discontinue
(settimeofday(2), clock_settime(2) ou similaire). Quand des
modifications se produisent, un appel actuel ou futur à read(2) à partir
du descripteur de fichier échouera avec l’erreur ECANCELED.
Si le paramètre old_value n'est pas égal à NULL, la structure
itimerspec vers laquelle il pointe est utilisée pour renvoyer la
configuration de la minuterie au moment de l'appel ; consultez la
description de timerfd_gettime() ci-dessous.
timerfd_gettime()
timerfd_gettime() renvoie, dans curr_value, une structure
itimerspec qui contient les paramètres actuels de la minuterie auquel le
descripteur de fichier fd fait référence.
Le champ it_value renvoie la durée jusqu'à la prochaine expiration. Si
les deux champs de cette structure sont nuls, alors la minuterie est
actuellement désactivée. Ce champ contient toujours une valeur relative,
sans tenir compte d'un attribut TFD_TIMER_ABSTIME qui aurait été spécifié
quand la minuterie a été configurée.
Le champ it_interval renvoie l'intervalle de la minuterie. Si les deux
champs de cette structure sont nuls, alors la minuteries est configurée pour
n'expirer qu'une seule fois, à l'heure spécifiée par curr_value.it_value.
Opérations sur un descripteur de fichier de minuterie
Le descripteur de fichier renvoyé par timerfd_create() gère les
opérations supplémentaires suivantes :
- read(2)
-
Si la minuterie a déjà expirée une fois ou plus depuis que sa configuration
a été modifiée la dernière fois à l'aide de timerfd_settime() ou depuis
la dernière lecture avec read(2) qui a réussi, alors le tampon fourni à
read(2) renvoie un entier non signé sur 8 octets (uint64_t) qui
contient le nombre d'expirations qui se sont produites. (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 aucune expiration ne s'est produite au moment de l'appel à read(2),
l'appel bloquera jusqu'à la prochaine expiration ou échouera avec l'erreur
EAGAIN si le descripteur de fichier est en mode non bloquant (à l'aide de
de l'opération F_SETFL de fcntl(2) pour régler l'attribut
O_NONBLOCK).
-
Un read(2) échouera avec l'erreur EINVAL si la taille du tampon fourni
est de moins de 8 octets.
-
Si l'horloge associée est soit CLOCK_REALTIME ou CLOCK_REALTIME_ALARM,
si la minuterie est absolue (TFD_TIMER_ABSTIME) et si l'attribut
TFD_TIMER_CANCEL_ON_SET a été spécifié lors de l'appel
timerfd_settime(), alors l'appel à read(2) échoue avec l'erreur
ECANCELED si l'horloge en temps réel subit une modification
discontinue. (Cela permet à l'application qui lit de découvrir ce type de
modifications discontinues à l'horloge.)
-
Si l'horloge associée est soit CLOCK_REALTIME ou CLOCK_REALTIME_ALARM,
si la minuterie est absolue (TFD_TIMER_ABSTIME) et si l'attribut
TFD_TIMER_CANCEL_ON_SET a été spécifié lors de l'appel
timerfd_settime(), alors une modification négative discontinue à
l'horloge (par exemple, clock_settime(2)) peut faire à que read(2)
supprime le blocage, mais renvoie une valeur de 0 (c'est-à-dire qu'aucun
octet n'est lu), si une modification d'horloge survient après que le temps
soit expiré, mais avant le read(2) sur le descripteur de fichier.
- poll(2), select(2) (et similaire)
-
Le descripteur de fichier est lisible (le paramètre readfds de
select(2) ; l'attribut POLLIN de poll(2)) si une expiration (ou
plus) de la minuterie s'est produite.
-
Le descripteur de fichier prend également en charge les autres interfaces de
multiplexage de descripteurs de fichier : pselect(2), ppoll(2) et
epoll(7).
- ioctl(2)
-
La commande suivante spécifique à timerfd est prise en charge :
-
- TFD_IOC_SET_TICKS (depuis Linux 3.17)
-
Ajuste le nombre d'expirations de minuterie qui sont survenues. Le paramètre
est un pointeur vers un entier de 8 octets différent de zéro (uint64_t*)
contenant le nouveau nombre d'expirations. Une fois que le nombre est
défini, tout processus en attente de la minuterie est réveillé. Le seul
objectif de cette commande est de rétablir les expirations dans l'objectif
de points de vérification ou de restauration. Cette opération est disponible
seulement si le noyau a été configuré avec l'option
CONFIG_CHECKPOINT_RESTORE.
- 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
minuterie ont été fermés, la minuterie est désarmée et ses ressources sont
libérées par le noyau.
Sémantique de fork(2)
Après un fork(2), l'enfant hérite d'une copie du descripteur de fichier
créé par timerfd_create(). Le descripteur de fichier se réfère au même
objet minuterie sous-jacent que le descripteur de fichier correspondant dans
le parent, et un read(2) de l'enfant renverra les informations sur les
expirations de la minuterie.
Sémantique de execve(2)
Un descripteur de fichier créé par timerfd_create() est conservé au
travers d'un execve(2), et continue à générer des expirations de
minuterie si la minuterie a été armée.
VALEUR RENVOYÉE
S'il réussit, timerfd_create() renvoie un nouveau descripteur de
fichier. En cas d'erreur, il renvoie -1 et errno est défini pour
indiquer l'erreur.
En cas de réussite, timerfd_settime() et timerfd_gettime() renvoient
0. Sinon ils renvoient -1 et définissent errno pour indiquer
l'erreur.
ERREURS
timerfd_create() peut échouer avec les erreurs suivantes :
- EINVAL
-
Le clockid n'est pas valable.
- EINVAL
-
flags n'est pas correct ; ou, pour les versions de Linux 2.6.26 ou
antérieures, flags n'est pas nul.
- EMFILE
-
La limite du nombre de descripteurs de fichiers par processus a été
atteinte.
- ENFILE
-
La limite du nombre total de fichiers ouverts pour le système entier a été
atteinte.
- ENODEV
-
Impossible de monter (en interne) le périphérique anonyme d'inœud.
- ENOMEM
-
Pas assez de mémoire noyau pour créer la minuterie.
- EPERM
-
clockid était CLOCK_REALTIME_ALARM ou CLOCK_BOOTTIME_ALARM, mais
l'appelant n'a pas la capacité CAP_WAKE_ALARM.
timerfd_settime() et timerfd_gettime() peuvent échouer avec les
erreurs suivantes :
- EBADF
-
fd n'est pas un descripteur de fichier valable.
- EFAULT
-
new_value, old_value ou curr_value n'est pas un pointeur valable.
- EINVAL
-
fd n'est pas un descripteur de fichier de minuterie valable.
timerfd_settime() peut aussi échouer avec les erreurs suivantes :
- ECANCELED
-
Voir NOTES
- EINVAL
-
new_value n'est pas initialisé correctement (un des champs tv_nsec est
en dehors de l'intervalle allant de 0 à 999 999 999).
- EINVAL
-
flags n'est pas correct.
VERSIONS
Ces appels système sont disponibles depuis Linux 2.6.25. La prise en charge
de la bibliothèque est fournie depuis la glibc 2.8.
STANDARDS
Ces appels système sont spécifiques à Linux.
NOTES
En supposant le scénario suivant pour une minuterie CLOCK_REALTIME ou
CLOCK_REALTIME_ALARM créée avec timerfd_create() :
- (1)
-
la minuterie a été démarrée (timerfd_settime()) avec les attributs
TFD_TIMER_ABSTIME et TFD_TIMER_CANCEL_ON_SET ;
- (2)
-
une modification discontinue (par exemple, settimeofday(2)) est ensuite
appliquée à l'horloge CLOCK_REALTIME ;
- (3)
-
l'appelant appelle une fois de plus timerfd_settime() pour réarmer la
minuterie (sans exécuter préalablement un read(2) sur le descripteur de
fichier).
Dans ce cas les événements suivants se produisent :
- •
-
timerfd_settime() renvoie -1 avec errno défini à
ECANCELED. (Cela permet à l'appelant de savoir que la minuterie
précédente a été affectée par une modification discontinue de l'horloge.)
- •
-
La minuterie est réarmée avec succès avec les réglages fournis dans le
second appel timerfd_settime(). (C'est probablement un accident
d'implémentation, mais ne sera pas corrigé maintenant au cas où des
applications dépendent de ce comportement.)
BOGUES
Actuellement, timerfd_create() prend en charge moins de types
d'identifiant d'horloges que timer_create(2).
EXEMPLES
Le programme suivant crée une minuterie puis surveille sa progression. Le
programme accepte jusqu'à trois paramètres en ligne de commande. Le premier
paramètre spécifie le nombre de secondes pour l'expiration initiale de la
minuterie. Le deuxième paramètre spécifie l'intervallse de la minuterie, en
secondes. Le troisième paramètre spécifie le nombre de fois que le programme
doit permettre à la minuterie d'expirer avant de quitter. Le deuxième et le
troisième paramètre sont optionnels.
La session interactive suivante montre l'utilisation de ce programme :
$ a.out 3 1 100
0.000: timer started
3.000: read: 1; total=1
4.000: read: 1; total=2
haZ # entrer Ctrl-Z pour suspendre le programme
[1]+ Stopped ./timerfd3_demo 3 1 100
$ fg # Reprendre l'exécution après quelques secondes
a.out 3 1 100
9.660: read: 5; total=7
10.000: read: 1; total=8
11.000: read: 1; total=9
haC # entrer Ctrl-C pour suspendre le programme
Source du programme
#include <err.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/timerfd.h>
#include <time.h>
#include <unistd.h>
static void
print_elapsed_time(void)
{
int secs, nsecs;
static int first_call = 1;
struct timespec curr;
static struct timespec start;
if (first_call) {
first_call = 0;
if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)
err(EXIT_FAILURE, "clock_gettime");
}
if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)
err(EXIT_FAILURE, "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[])
{
int fd;
ssize_t s;
uint64_t exp, tot_exp, max_exp;
struct timespec now;
struct itimerspec new_value;
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)
err(EXIT_FAILURE, "clock_gettime");
/* Créer une minuterie absolue CLOCK_REALTIME avec une expiration
et un intervalle initiaux comme spécifié en ligne de commande. */
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)
err(EXIT_FAILURE, "timerfd_create");
if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
err(EXIT_FAILURE, "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))
err(EXIT_FAILURE, "read");
tot_exp += exp;
print_elapsed_time();
printf("read: %" PRIu64 "; total=%" PRIu64 "\n", exp, tot_exp);
}
exit(EXIT_SUCCESS);
}
VOIR AUSSI
eventfd(2), poll(2), read(2), select(2), setitimer(2),
signalfd(2), timer_create(2), timer_gettime(2),
timer_settime(2), timespec(3), epoll(7), time(7)
TRADUCTION
La traduction française de cette page de manuel a été créée par
Christophe Blaess <https://www.blaess.fr/christophe/>,
Stéphan Rafin <stephan.rafin@laposte.net>,
Thierry Vignaud <tvignaud@mandriva.com>,
François Micaux,
Alain Portal <aportal@univ-montp2.fr>,
Jean-Philippe Guérard <fevrier@tigreraye.org>,
Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>,
Julien Cristau <jcristau@debian.org>,
Thomas Huriaux <thomas.huriaux@gmail.com>,
Nicolas François <nicolas.francois@centraliens.net>,
Florentin Duneau <fduneau@gmail.com>,
Simon Paillard <simon.paillard@resel.enst-bretagne.fr>,
Denis Barbier <barbier@debian.org>,
David Prévot <david@tilapin.org>,
Cédric Boutillier <cedric.boutillier@gmail.com>,
Frédéric Hantrais <fhantrais@gmail.com>
et
Jean-Pierre Giraud <jean-pierregiraud@neuf.fr>
Cette traduction est une documentation libre ; veuillez vous reporter à la
GNU General Public License version 3
concernant les conditions de copie et
de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
Index
- NOM
-
- BIBLIOTHÈQUE
-
- SYNOPSIS
-
- DESCRIPTION
-
- timerfd_create()
-
- timerfd_settime()
-
- timerfd_gettime()
-
- Opérations sur un descripteur de fichier de minuterie
-
- Sémantique de fork(2)
-
- Sémantique de execve(2)
-
- VALEUR RENVOYÉE
-
- ERREURS
-
- VERSIONS
-
- STANDARDS
-
- NOTES
-
- BOGUES
-
- EXEMPLES
-
- Source du programme
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 09:21:20 GMT, May 23, 2024