.\" -*- coding: UTF-8 -*- .\" Copyright (c) 2009 Linux Foundation, written by Michael Kerrisk .\" .\" .\" SPDX-License-Identifier: Linux-man-pages-copyleft .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH timer_create 2 "3 мая 2023 г." "Linux man\-pages 6.05.01" .SH ИМЯ timer_create \- создаёт таймер POSIX для определённого процесса .SH LIBRARY Real\-time library (\fIlibrt\fP, \fI\-lrt\fP) .SH СИНТАКСИС .nf \fB#include \fP /* определения констант \fBSIGEV_*\fP */ \fB#include \fP .PP \fBint timer_create(clockid_t \fP\fIclockid\fP\fB,\fP \fB struct sigevent *_Nullable restrict \fP\fIsevp\fP\fB,\fP \fB timer_t *restrict \fP\fItimerid\fP\fB);\fP .fi .PP .RS -4 Требования макроса тестирования свойств для glibc (см. \fBfeature_test_macros\fP(7)): .RE .PP \fBtimer_create\fP(): .nf _POSIX_C_SOURCE >= 199309L .fi .SH ОПИСАНИЕ Вызов \fBtimer_create\fP() создаёт новый таймер для процесса. Идентификатор нового таймера возвращается в буфере, указанном в \fItimerid\fP, его значение не должно быть равно null. Данный идентификатор уникален для процесса, пока таймер не будет удалён. Новый таймер создаётся неактивным. .PP В аргументе \fIclockid\fP задаются часы, которые используются в новом таймере для учёта времени. Это может быть одно из следующих значений: .TP \fBCLOCK_REALTIME\fP Настраиваемые системные часы реального времени. .TP \fBCLOCK_MONOTONIC\fP .\" Note: the CLOCK_MONOTONIC_RAW clock added for clock_gettime() .\" in Linux 2.6.28 is not supported for POSIX timers -- mtk, Feb 2009 Ненастраиваемые, постоянно идущие вперёд часы, отсчитывающие время с некоторой неопределённой точки в прошлом, которая не изменяется с момент запуска системы. .TP \fBCLOCK_PROCESS_CPUTIME_ID\fP (начиная с Linux 2.6.12) Часы, измеряющие время ЦП (пользовательское и системное), затраченное вызывающим процессом (всеми его нитями). .TP \fBCLOCK_THREAD_CPUTIME_ID\fP (начиная с Linux 2.6.12) .\" The CLOCK_MONOTONIC_RAW that was added in Linux 2.6.28 can't be used .\" to create a timer -- mtk, Feb 2009 Часы, измеряющие время ЦП (пользовательское и системное), затраченное вызывающей нитью. .TP \fBCLOCK_BOOTTIME\fP (начиная с Linux 2.6.39) .\" commit 70a08cca1227dc31c784ec930099a4417a06e7d0 Подобно \fBCLOCK_MONOTONIC\fP, представляет монотонно растущие часы. Однако, если часы \fBCLOCK_MONOTONIC\fP не отсчитывают время когда система находится в состоянии ожидания (suspended), а часы \fBCLOCK_BOOTTIME\fP учитывают время в таком состоянии системы. Это полезно приложениям, которым необходимо учитывать состояние ожидания. \fBCLOCK_REALTIME\fP не подходят для таких приложений, так как эти часы подвержены скачкообразным изменениям системных часов. .TP \fBCLOCK_REALTIME_ALARM\fP (начиная с Linux 3.0) .\" commit 9a7adcf5c6dea63d2e47e6f6d2f7a6c9f48b9337 Эти часы подобны \fBCLOCK_REALTIME\fP, но разбудят систему, если она находится с состоянии ожидания. Для установки таймера по этим часам вызывающий должен иметь мандат \fBCAP_WAKE_ALARM\fP. .TP \fBCLOCK_BOOTTIME_ALARM\fP (начиная с Linux 3.0) .\" commit 9a7adcf5c6dea63d2e47e6f6d2f7a6c9f48b9337 Эти часы подобны \fBCLOCK_BOOTTIME\fP, но разбудят систему, если она находится с состоянии ожидания. Для установки таймера по этим часам вызывающий должен иметь мандат \fBCAP_WAKE_ALARM\fP. .TP \fBCLOCK_TAI\fP (начиная с Linux 3.10) A system\-wide clock derived from wall\-clock time but ignoring leap seconds. .PP See \fBclock_getres\fP(2) for some further details on the above clocks. .PP Помимо значений, перечисленных ранее, в \fIclockid\fP может быть указано \fIclockid\fP, возвращённое вызовом \fBclock_getcpuclockid\fP(3) или \fBpthread_getcpuclockid\fP(3). .PP Аргумент \fIsevp\fP указывает на структуру \fIsigevent\fP, которая задаёт способ уведомления вызывающего при срабатывании таймера. Определение и описание структуры смотрите в \fBsigevent\fP(7). .PP В поле \fIsevp.sigev_notify\fP можно указать следующие значения: .TP \fBSIGEV_NONE\fP Выполнять синхронное уведомление при срабатывании таймера. Ход таймера можно отслеживать с помощью \fBtimer_gettime\fP(2). .TP \fBSIGEV_SIGNAL\fP При срабатывании таймера генерировать для процесса сигнал \fIsigev_signo\fP. Подробности смотрите в \fBsigevent\fP(7). Полю \fIsi_code\fP структуры \fIsiginfo_t\fP присваивается значение \fBSI_TIMER\fP. В любой момент времени для таймера в очередь процесса ставится не более одного сигнала; подробности смотрите в \fBtimer_getoverrun\fP(2). .TP \fBSIGEV_THREAD\fP При срабатывании вызвать \fIsigev_notify_function\fP, как если бы это была начальная функция новой нити. Подробности смотрите в \fBsigevent\fP(7). .TP \fBSIGEV_THREAD_ID\fP (есть только в Linux) Как для \fBSIGEV_SIGNAL\fP, но сигнал нацелен на нить, чей ID указывается в \fIsigev_notify_thread_id\fP, который должен быть нитью того же процесса что и вызывающий. В поле \fIsigev_notify_thread_id\fP указывается ID ядерной нити, то есть значение, возвращаемое \fBclone\fP(2) или \fBgettid\fP(2). Этот флаг предназначен только для использования в библиотеках нитей. .PP Указание в \fIsevp\fP значения NULL эквивалентно указанию указателя на структуру \fIsigevent\fP, в которой \fIsigev_notify\fP равно \fBSIGEV_SIGNAL\fP, \fIsigev_signo\fP равно \fBSIGALRM\fP и \fIsigev_value.sival_int\fP равно ID таймера. .SH "ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ" При успешном выполнении \fBtimer_create\fP() возвращается 0 и ID нового таймера помещается в \fI*timerid\fP. При ошибке возвращается \-1, а \fIerrno\fP устанавливается в соответствующее значение. .SH ОШИБКИ .TP \fBEAGAIN\fP Временная ошибка, на время выделения ядром структур таймера. .TP \fBEINVAL\fP Некорректный ID часов, \fIsigev_notify\fP, \fIsigev_signo\fP или \fIsigev_notify_thread_id\fP. .TP \fBENOMEM\fP .\" glibc layer: malloc() Невозможно выделить память. .TP \fBENOTSUP\fP The kernel does not support creating a timer against this \fIclockid\fP. .TP \fBEPERM\fP \fIclockid\fP was \fBCLOCK_REALTIME_ALARM\fP or \fBCLOCK_BOOTTIME_ALARM\fP but the caller did not have the \fBCAP_WAKE_ALARM\fP capability. .SH ВЕРСИИ .SS "Отличия между библиотекой C и ядром" .\" See nptl/sysdeps/unix/sysv/linux/timer_create.c Частично, реализация программного интерфейса таймеров POSIX предоставляется glibc. А именно: .IP \[bu] 3 Большая часть функций для \fBSIGEV_THREAD\fP реализована в glibc, а не в ядре (это необходимо, так как в обработку уведомления вовлечена нить, которая должна управляться библиотекой C, реализующей нити POSIX). Хотя уведомление доставляется процессу через нить, внутри реализации NPTL для \fBSIGEV_THREAD_ID\fP используется значение \fIsigev_notify\fP и сигнал реального времени, который зарезервирован для реализации (смотрите \fBnptl\fP(7)). .IP \[bu] Стандартная ситуация, когда \fIevp\fP равно NULL, обрабатывается в glibc, где вызывается нижележащий системный вызов с заполненной подходящим образом структурой \fIsigevent\fP. .IP \[bu] .\" See the glibc source file kernel-posix-timers.h for the structure .\" that glibc uses to map user-space timer IDs to kernel timer IDs .\" The kernel-level timer ID is exposed via siginfo.si_tid. Идентификаторы таймеров, обрабатываемые на уровне пользователя, поддерживаются glibc, которая отображает эти ID в ID таймеров, созданных ядром. .SH СТАНДАРТЫ POSIX.1\-2008. .SH ИСТОРИЯ Linux 2.6. POSIX.1\-2001. .PP .\" glibc commit 93a78ac437ba44f493333d7e2a4b0249839ce460 Prior to Linux 2.6, glibc provided an incomplete user\-space implementation (\fBCLOCK_REALTIME\fP timers only) using POSIX threads, and before glibc 2.17, the implementation falls back to this technique on systems running kernels older than Linux 2.6. .SH ЗАМЕЧАНИЯ С помощью \fBtimer_create\fP() программа может создавать несколько интервальных таймеров. .PP Таймеры не наследуются в потомке после \fBfork\fP(2), и выключаются и удаляются при \fBexecve\fP(2). .PP Ядро заранее выделяет «сигнал реального времени в очереди» для каждого таймера, создаваемого \fBtimer_create\fP(). В результате, количество таймеров ограничено ресурсом \fBRLIMIT_SIGPENDING\fP (смотрите \fBsetrlimit\fP(2)). .PP Таймеры, созданные \fBtimer_create\fP(), часто называют «(интервальными) таймерами POSIX». Программный интерфейс таймеров POSIX состоит из следующих интерфейсов: .TP \fBtimer_create\fP() Create a timer. .TP \fBtimer_settime\fP(2) Arm (start) or disarm (stop) a timer. .TP \fBtimer_gettime\fP(2) Fetch the time remaining until the next expiration of a timer, along with the interval setting of the timer. .TP \fBtimer_getoverrun\fP(2) Return the overrun count for the last timer expiration. .TP \fBtimer_delete\fP(2) Disarm and delete a timer. .PP Начиная с Linux 3.10, файл \fI/proc/\fPpid\fI/timers\fP можно использовать для просмотра списка таймеров POSIX для процесса с PID равным \fIpid\fP. Подробности смотрите в \fBproc\fP(5). .PP .\" baa73d9e478ff32d62f3f9422822b59dd9a95a21 Начиная с Linux 4.10, поддержка таймеров POSIX теперь необязательна и включена по умолчанию. Поддержку в ядре можно выключить через параметр \fBCONFIG_POSIX_TIMERS\fP. .SH ПРИМЕРЫ Программа ниже обрабатывает два аргумента: интервал сна в секундах и частоту таймера в наносекундах. Программа устанавливает обработчик сигнала для таймера, блокирует этот сигнал, создаёт и включает таймер, который срабатывает с заданной частотой, засыпает на указанное количество секунд, а после разблокирует сигнал таймера. Предполагая, что таймер сработает не менее одного раза пока программа спит, обработчик сигнала будет вызван и покажет некоторую информацию об уведомлении таймера. Программа завершается после одного вызова обработчика сигнала. .PP В следующем примере программа спит 1 секунду после создания таймера, который работает с частотой 100 наносекунд. За время разблокировки и доставки сигнала, произошло около 10 миллионов переполнений. .PP .in +4n .EX \&./$ \fB./a.out 1 100\fP Устанавливается обработчик сигнала 34 Блокируется сигнал 34 ID таймера — 0x804c008 Спим 1 секунду Разблокируется сигнал 34 Пойман сигнал 34 sival_ptr = 0xbfb174f4; *sival_ptr = 0x804c008 счётчик переполнения = 10004886 .EE .in .SS "Исходный код программы" .\" SRC BEGIN (timer_create.c) \& .EX #include #include #include #include #include #include \& #define CLOCKID CLOCK_REALTIME #define SIG SIGRTMIN \& #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e } 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\en", (uintmax_t) *tidp); \& or = timer_getoverrun(*tidp); if (or == \-1) errExit("timer_getoverrun"); else printf(" overrun count = %d\en", or); } \& static void handler(int sig, siginfo_t *si, void *uc) { /* Note: calling printf() from a signal handler is not safe (and should not be done in production programs), since printf() is not async\-signal\-safe; see signal\-safety(7). Nevertheless, we use printf() here as a simple way of showing that the handler was called. */ \& printf("Caught signal %d\en", 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 \en", argv[0]); exit(EXIT_FAILURE); } \& /* Establish handler for timer signal. */ \& printf("Establishing handler for signal %d\en", SIG); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = handler; sigemptyset(&sa.sa_mask); if (sigaction(SIG, &sa, NULL) == \-1) errExit("sigaction"); \& /* Block timer signal temporarily. */ \& printf("Blocking signal %d\en", SIG); sigemptyset(&mask); sigaddset(&mask, SIG); if (sigprocmask(SIG_SETMASK, &mask, NULL) == \-1) errExit("sigprocmask"); \& /* Create the timer. */ \& 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\en", (uintmax_t) timerid); \& /* Start the timer. */ \& 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"); \& /* Sleep for a while; meanwhile, the timer may expire multiple times. */ \& printf("Sleeping for %d seconds\en", atoi(argv[1])); sleep(atoi(argv[1])); \& /* Unlock the timer signal, so that timer notification can be delivered. */ \& printf("Unblocking signal %d\en", SIG); if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == \-1) errExit("sigprocmask"); \& exit(EXIT_SUCCESS); } .EE .\" SRC END .SH "СМ. ТАКЖЕ" .ad l .nh \fBclock_gettime\fP(2), \fBsetitimer\fP(2), \fBtimer_delete\fP(2), \fBtimer_getoverrun\fP(2), \fBtimer_settime\fP(2), \fBtimerfd_create\fP(2), \fBclock_getcpuclockid\fP(3), \fBpthread_getcpuclockid\fP(3), \fBpthreads\fP(7), \fBsigevent\fP(7), \fBsignal\fP(7), \fBtime\fP(7) .PP .SH ПЕРЕВОД Русский перевод этой страницы руководства был сделан Azamat Hackimov , Dmitry Bolkhovskikh , Yuri Kozlov и Иван Павлов . .PP Этот перевод является бесплатной документацией; прочитайте .UR https://www.gnu.org/licenses/gpl-3.0.html Стандартную общественную лицензию GNU версии 3 .UE или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ. .PP Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на .MT man-pages-ru-talks@lists.sourceforge.net .ME .