timer_create(2) System Calls Manual timer_create(2) NOM timer_create - Creer une minuterie POSIX pour un processus BIBLIOTHEQUE Bibliotheque de temps reel (librt, -lrt) SYNOPSIS #include /* Definition des constantes SIGEV_* */ #include int timer_create(clockid_t clockid, struct sigevent *_Nullable restrict sevp, timer_t *restrict timerid); Exigences de macros de test de fonctionnalites pour la glibc (consulter feature_test_macros(7)) : timer_create() : _POSIX_C_SOURCE >= 199309L DESCRIPTION timer_create() cree une nouvelle minuterie d'intervalle par un processus. L'identifiant de cette nouvelle minuterie est renvoye dans le tampon pointe par timerid, qui doit etre un pointeur different de NULL. L'identifiant est unique pour le processus, jusqu'a ce que la minuterie soit detruite. La nouvelle minuterie est initialement desarmee. Le parametre clockid indique l'horloge que la nouvelle minuterie utilise pour mesurer le temps. Il peut prendre une des valeurs suivantes : CLOCK_REALTIME Une horloge temps reel configurable a l'echelle du systeme. CLOCK_MONOTONIC Une horloge non configurable, toujours croissante qui mesure le temps depuis un instant non specifie dans le passe et qui ne change pas apres le demarrage du systeme. CLOCK_PROCESS_CPUTIME_ID (depuis Linux 2.6.12) Une horloge qui mesure le temps CPU (utilisateur et systeme) consomme par le processus appelant (et tous ses threads). CLOCK_THREAD_CPUTIME_ID (depuis Linux 2.6.12) Une horloge qui mesure le temps CPU (utilisateur et systeme) consomme par le processus appelant. CLOCK_BOOTTIME (depuis Linux 2.6.39) 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 systeme est suspendu, l'horloge CLOCK_BOOTTIME inclut le temps pendant lequel le systeme est suspendu. Cela est utile pour les applications qui doivent etre sensibles au temps de suspension. CLOCK_REALTIME n'est pas adapte a ce type d'application dans la mesure ou cette horloge est affectee par des modifications discontinues de l'horloge systeme. CLOCK_REALTIME_ALARM (depuis Linux 3.0) Cette horloge se comporte comme CLOCK_REALTIME, mais reveillera le systeme s'il est suspendu. L'appelant doit avoir la capacite CAP_WAKE_ALARM afin de regler une minuterie utilisant cette horloge. CLOCK_BOOTTIME_ALARM (depuis Linux 3.0) Cette horloge se comporte comme CLOCK_BOOTTIME, mais reveillera le systeme s'il est suspendu. L'appelant doit avoir la capacite CAP_WAKE_ALARM afin de regler une minuterie utilisant cette horloge. CLOCK_TAI (depuis Linux 3.10) Horloge derivee d'une pendule mais qui compte les secondes intercalaires. Consultez clock_getres(2) pour quelques details supplementaires sur les horloges mentionnees. Comme pour les valeurs ci-dessus, clockid peut etre l'identifiant clockid renvoye par un appel a clock_getcpuclockid(3) ou pthread_getcpuclockid(3). The sevp argument points to a sigevent structure that specifies how the caller should be notified when the timer expires. For the definition and general details of this structure, see sigevent(3type). Le champ sevp.sigev_notify peut avoir les valeurs suivantes : SIGEV_NONE Ne pas notifier de facon asynchrone quand la minuterie expire. La progression de la minuterie peut etre observee en utilisant timer_gettime(2). SIGEV_SIGNAL Upon timer expiration, generate the signal sigev_signo for the process. See sigevent(3type) for general details. The si_code field of the siginfo_t structure will be set to SI_TIMER. At any point in time, at most one signal is queued to the process for a given timer; see timer_getoverrun(2) for more details. SIGEV_THREAD Upon timer expiration, invoke sigev_notify_function as if it were the start function of a new thread. See sigevent(3type) for details. SIGEV_THREAD_ID (specifique a Linux) Comme SIGEV_SIGNAL, mais le signal est envoye au thread dont l'identifiant est fourni dans sigev_notify_thread_id, qui doit etre un thread du meme processus que le thread appelant. Le champ sigev_notify_thread_id indique un identifiant de thread noyau, c'est-a-dire la valeur renvoyee par clone(2) ou gettid(2). Ce drapeau n'est destine a etre utilise que par la bibliotheque des threads. Une valeur NULL pour sevp equivaut a indiquer un pointeur vers une structure sigevent dans laquelle sigev_notify vaut SIGEV_SIGNAL, sigev_signo vaut SIGALRM et sigev_value.sival_int vaut l'identifiant de l'horloge. VALEUR RENVOYEE S'il reussit, timer_create() renvoie 0 et l'identifiant de la nouvelle minuterie est place dans *timerid. En cas d'erreur, il renvoie -1 et errno est defini pour indiquer l'erreur. ERREURS EAGAIN Erreur temporaire lors de l'allocation de la structure de la minuterie par le noyau. EINVAL L'identifiant d'horloge, sigev_notify, sigev_signo ou sigev_notify_thread_id n'est pas valable. ENOMEM La memoire n'a pu etre allouee. ENOTSUP Le noyau ne gere pas la creation d'une minuterie utilisant ce clockid. EPERM clockid etait CLOCK_REALTIME_ALARM ou CLOCK_BOOTTIME_ALARM, mais l'appelant n'a pas la capacite CAP_WAKE_ALARM. VERSIONS Differences entre bibliotheque C et noyau Une partie de l'implementation des API de minuteries POSIX est fournie par la glibc. En particulier : - L'essentiel des fonctionnalites pour SIGEV_THREAD est implemente dans la glibc plutot que dans le noyau. (C'est forcement ainsi dans la mesure ou le thread implique dans la gestion de la notification est un de ceux qui doit etre gere par l'implementation des threads POSIX de la bibliotheque C.) Bien que la notification fournie par le processus est faite au moyen d'un thread, en interne l'implementation de NPTL utilise une valeur sigev_notify de SIGEV_THREAD_ID en meme temps qu'un signal en temps reel qui est reserve par l'implementation (consultez nptl(7)). - L'implementation du cas par defaut ou evp est NULL est geree dans glibc qui invoque l'appel systeme sous-jacent avec une structure sigevent remplie de facon appropriee. - Les identifiants de minuteries fournis au niveau utilisateur sont maintenus par la glibc, qui fait la correspondance avec les identifiants utilises par le noyau. STANDARDS POSIX.1-2008. HISTORIQUE Linux 2.6. POSIX.1-2001. Avant Linux 2.6, la glibc fournissait une implementation incomplete en espace utilisateur (les minuteries CLOCK_REALTIME uniquement) en utilisant les threads POSIX, et avant la glibc 2.17, l'implementation se replie sur cette technique sur les systemes ayant un noyau anterieur a Linux 2.6. NOTES Un programme peut creer plusieurs minuteries d'intervalle en utilisant timer_create(). Les minuteries ne sont pas heritees par l'enfant d'un fork(2) et sont desarmees et detruites lors d'un appel systeme execve(2). Le noyau alloue par avance un << signal temps reel en attente >> pour chaque minuterie creee par timer_create(). De ce fait, le nombre de minuteries est limite par la limite de ressources RLIMIT_SIGPENDING (voir setrlimit(2)). Les minuteries creees par timer_create() sont communement appelees << minuteries (d'intervalle) POSIX >>. L'API des minuteries POSIX est constituee des interfaces suivantes : timer_create() Creer une minuterie. timer_settime(2) Armer (demarrer) ou desarmer (stopper) une minuterie. timer_gettime(2) Recuperer le temps restant jusqu'a l'expiration suivante d'une minuterie, en plus de l'intervalle de la minuterie. timer_getoverrun(2) Renvoyer le decompte de depassements pour la derniere expiration de la minuterie. timer_delete(2) Desarmer et detruire une minuterie. Depuis Linux 3.10, le fichier /proc/pid/timers peut etre utilise pour lister les minuteries POSIX du processus de PID pid. Consultez proc(5) pour plus de details. Depuis Linux 4.10, la prise en charge des minuteries de POSIX est une option configurable qui est activee par defaut. La prise en charge du noyau peut etre desactivee au moyen de l'option CONFIG_POSIX_TIMERS. EXEMPLES Le programme ci-dessous recoit deux parametres : une duree de sommeil, en seconde, et une frequence de minuterie en nanosecondes. Le programme etablit un gestionnaire pour le signal qu'il utilise pour la minuterie, puis il bloque le signal, cree et arme une minuterie qui expire a la frequence donnee, s'endort pendant la duree indiquee et enfin debloque le signal de la minuterie. En supposant que la minuterie ait expire au moins une fois pendant le sommeil du programme, le gestionnaire de signal sera appele et le gestionnaire de signal affiche des informations concernant la notification de la minuterie. Le programme se termine apres un appel au gestionnaire de signal. Dans l'exemple d'execution qui suit, le programme s'endort pour une seconde apres avoir cree une minuterie de frequence de 100 nanosecondes. Le temps que le signal soit debloque et fourni, il y a eu environ dix millions de depassements. $ ./a.out 1 100 Establishing handler for signal 34 Blocking signal 34 timer ID is 0x804c008 Sleeping for 1 seconds Unblocking signal 34 Caught signal 34 sival_ptr = 0xbfb174f4; *sival_ptr = 0x804c008 overrun count = 10004886 Source du programme #include #include #include #include #include #include #define CLOCKID CLOCK_REALTIME #define SIG SIGRTMIN #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0) static void print_siginfo(siginfo_t *si) { int or; timer_t *tidp; tidp = si->si_value.sival_ptr; printf(" sival_ptr = %p; ", si->si_value.sival_ptr); printf(" *sival_ptr = %#jx\n", (uintmax_t) *tidp); or = timer_getoverrun(*tidp); if (or == -1) errExit("timer_getoverrun"); else printf(" overrun count = %d\n", or); } static void handler(int sig, siginfo_t *si, void *uc) { /* Remarque : l'appel printf() a partir d'un gestionnaire de signal n'est pas strictement correct (et ne devrait pas etre utilise en production) dans la mesure ou printf() n'est pas sur dans un contexte de signal asynchrone ; consultez signal(7). Neanmoins, printf() est utilise ici comme une maniere simple de montrer que le gestionnaire a ete appele. */ printf("Caught signal %d\n", sig); print_siginfo(si); signal(sig, SIG_IGN); } int main(int argc, char *argv[]) { timer_t timerid; sigset_t mask; long long freq_nanosecs; struct sigevent sev; struct sigaction sa; struct itimerspec its; if (argc != 3) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } /* Etablir un gestionnaire pour le signal de minuterie. */ printf("Establishing handler for signal %d\n", SIG); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = handler; sigemptyset(&sa.sa_mask); if (sigaction(SIG, &sa, NULL) == -1) errExit("sigaction"); /* Bloquer temporairement un signal de minuterie. */ printf("Blocking signal %d\n", SIG); sigemptyset(&mask); sigaddset(&mask, SIG); if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) errExit("sigprocmask"); /* Creer la minuterie. */ sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIG; sev.sigev_value.sival_ptr = &timerid; if (timer_create(CLOCKID, &sev, &timerid) == -1) errExit("timer_create"); printf("timer ID is %#jx\n", (uintmax_t) timerid); /* Demarrer la minuterie. */ freq_nanosecs = atoll(argv[2]); its.it_value.tv_sec = freq_nanosecs / 1000000000; its.it_value.tv_nsec = freq_nanosecs % 1000000000; its.it_interval.tv_sec = its.it_value.tv_sec; its.it_interval.tv_nsec = its.it_value.tv_nsec; if (timer_settime(timerid, 0, &its, NULL) == -1) errExit("timer_settime"); /* Mettre en sommeil un moment : pendant ce temps, la minuterie peut expirer plusieurs fois */ printf("Sleeping for %d seconds\n", atoi(argv[1])); sleep(atoi(argv[1])); /* Debloquer le signal de minuterie, de sorte que la notification peut etre fournie */ printf("Unblocking signal %d\n", SIG); if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) errExit("sigprocmask"); exit(EXIT_SUCCESS); } VOIR AUSSI clock_gettime(2), setitimer(2), timer_delete(2), timer_getoverrun(2), timer_settime(2), timerfd_create(2), clock_getcpuclockid(3), pthread_getcpuclockid(3), pthreads(7), sigevent(3type), signal(7), time(7) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot , Cedric Boutillier , Frederic Hantrais et Jean-Pierre Giraud Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 11 novembre 2023 timer_create(2)