| timerfd_create(2) | System Calls Manual | timerfd_create(2) |
timerfd_create, timerfd_settime, timerfd_gettime - таймеры, уведомляющие через файловые дескрипторы
Стандартная библиотека языка C (libc, -lc)
#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);
Эти системные вызовы создают и работают с таймером, доставляя уведомления о срабатывании через файловый дескриптор. Они предоставляют альтернативу setitimer(2) или timer_create(2); их преимущество в том, что за файловым дескриптором можно следить с помощью select(2), poll(2) и epoll(7).
Использование данных трёх системных вызовов аналогично timer_create(2), timer_settime(2) и timer_gettime(2) (аналога timer_getoverrun(2) нет, так как его возможности предоставляет read(2) как описано ниже).
Вызов timerfd_create() создаёт новый объект таймера и возвращает файловый дескриптор, который ссылается на этот таймер. В аргументе clockid задаются часы, которые используются для хода таймера; значением должно быть одно из следующих:
See clock_getres(2) for some further details on the above clocks.
Текущее значение каждого из этих часов можно получить с помощью clock_gettime(2).
Начиная с Linux 2.6.27, для изменения поведения timerfd_create() можно использовать следующие значения flags (через OR):
До Linux 2.6.26 включительно аргумент flags должен быть равен нулю.
Вызов timerfd_settime() запускает или останавливает таймер, на который ссылается файловый дескриптор fd.
The new_value argument specifies the initial expiration and interval for the timer. The itimerspec structure used for this argument is described in itimerspec(3type).
В new_value.it_value задаётся первое срабатывание таймера, в секундах и наносекундах. Установка любого из полей new_value.it_value в ненулевое значение включает таймер. Установка обоих полей new_value.it_value в ноль выключает таймер.
Установка одного или обоих полей new_value.it_interval в ненулевое значение задаёт период, в секундах и наносекундах, периодического срабатывания таймера после первого срабатывания. Если оба поля new_value.it_interval равны нулю, то таймер срабатывает только один раз, во время, указанное в new_value.it_value.
По умолчанию, начальное время срабатывания, задаваемое в new_value, считается относительно текущего времени часов таймера на момент вызова (т. е., в new_value.it_value задаётся время относительно текущего значения часов, заданных в clockid). Использование абсолютной задержки можно включить через аргумент flags.
Аргумент flags является битовой маской, которая может включать следующие значения:
Если old_value не равно NULL, то это указатель на структуру itimerspec, и он будет использоваться для возврата текущих на момент вызова настроек таймера; смотрите описание timerfd_gettime() далее.
Вызов timerfd_gettime() возвращает в curr_value, которое указывает на структуру itimerspec, текущие настройки таймера, на который ссылается файловый дескриптор fd.
В поле it_value возвращается время до следующего срабатывания таймера. Если оба поля этой структуры равны нулю, то таймер в данный момент не запущен. Это поле всегда содержит относительное значение, независимо от того, был ли указан флаг TFD_TIMER_ABSTIME при настройке таймера.
В поле it_interval возвращается интервал таймера. Если оба поля этой структуры равны нулю, то таймер настроен на однократное срабатывание, на время, заданное в curr_value.it_value.
The file descriptor returned by timerfd_create() supports the following additional operations:
После fork(2) потомки наследуют копию файлового дескриптора, созданного timerfd_create(). Файловый дескриптор потомка ссылается на тот же объект таймера, что и файловый дескриптор его родителя, и операция read(2) в потомке будет возвращать информацию о срабатываниях таймера.
Файловый дескриптор, созданный timerfd_create(), сохраняется при execve(2), и продолжает генерировать срабатывания таймера, если он включён.
При успешном выполнении timerfd_create() возвращает новый файловый дескриптор. При ошибке возвращается -1, и errno устанавливается в соответствующее значение.
При успешном выполнении timerfd_settime() и timerfd_gettime() возвращают 0; в случае ошибки возвращается -1, а errno устанавливается в соответствующее значение ошибки.
Вызов timerfd_create() может завершиться со следующими ошибками:
Вызовы timerfd_settime() и timerfd_gettime() могут завершаться со следующими ошибками:
Вызов timerfd_settime() также может завершиться со следующими ошибками:
Linux.
Linux 2.6.25, glibc 2.8.
Suppose the following scenario for CLOCK_REALTIME or CLOCK_REALTIME_ALARM timer that was created with timerfd_create():
In this case the following occurs:
В настоящее время timerfd_create() поддерживает только несколько типов идентификаторов часов, поддерживаемых timer_create(2).
Следующая программа создаёт таймер и затем следит за его работой. Программа получает до трёх аргументов из командной строки. В первом аргументе задаётся количество секунд до первого срабатывания таймера. Во втором аргументе задаётся интервал таймера в секундах. В третьем аргументе задаётся сколько программа должна позволить сработать таймеру до завершения. Второй и третий аргументы необязательны.
Следующий сеанс работы в оболочке показывает работу с программой:
$ a.out 3 1 100 0.000: timer started 3.000: read: 1; total=1 4.000: read: 1; total=2 ^Z # 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 ^C # type control-C to suspend the program
#include <err.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/timerfd.h>
#include <sys/types.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");
/* 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)
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);
}
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)
Русский перевод этой страницы руководства разработал(и) Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, Yuri Kozlov <yuray@komyakino.ru>, Иван Павлов <pavia00@gmail.com> и Kirill Rekhov <krekhov.dev@gmail.com>
Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков.
| 15 июня 2024 г. | Справочные страницы Linux 6.9.1 |