Книга: Разработка приложений в среде Linux. Второе издание
18.2.2. Интервальные таймеры
18.2.2. Интервальные таймеры
Интервальные таймеры, будучи активизированными, непрерывно передают сигналы в процесс на систематической основе. Точное значение термина систематический зависит от используемого интервального таймера. С каждым процессом ассоциированы три таймера.
ITIMER_REAL |
Отслеживает время в терминах настенных часов — в реальном времени (в зависимости от выполнения процесса) — и генерирует сигнал SIGALRM. Несовместим с системным вызовом alarm() , который используется функцией sleep() . Не применяйте ни alarm() , ни sleep() , если имеется реальный интервальный таймер. |
ITIMER_VIRTUAL |
Подсчитывает время только при исполнении процесса — не учитывая системные вызовы, которые производит процесс — и генерирует сигнал SIGVTALRM . |
ITIMER_PROF |
Подсчитывает время только при выполнении процесса — включая время, за которое ядро посылает исполнительные системные вызовы от имени процесса, и не включая время, потраченное на прерывание процесса по инициативе самого процесса — и генерирует сигнал SIGPROF . Учет времени, затраченного на обработку прерываний, оказывается настолько трудоемким, что даже может изменить настройки таймера. |
Комбинация таймеров ITIMER_VIRTUAL
и ITIMER_PROF
часто используется в профилирующих кодах.
Каждый из этих таймеров генерирует ассоциированный сигнал об истечении таймера в пределах одного хода системных часов (как правило, 1-10 миллисекунд). Если процесс работает в данное время, то сигнал генерируется сразу же; в противном случае сигнал генерируется немного позже (в зависимости от загрузки системы). Поскольку таймер ITIMER_VIRTUAL
следит за временем только во время работы процесса, то сигнал всегда доставляется незамедлительно.
Используйте структуру struct itimerval
для передачи запроса и установки интервальных таймеров.
struct itimerval {
struct timeval it_interval;
struct timeval it_value;
};
Член it_value
показывает количество времени, оставшееся до отправления следующего сигнала. Член it_interval
определяет время между сигналами; каждый раз при истечении таймера это значение присваивается переменной it_value
.
Для взаимодействия с интервальными таймерами предусмотрены два системных вызова. Оба принимают аргумент which
, указывающий обрабатываемый таймер.
int getitimer(int which, struct itimerval *val);
Переменной val
присваивается текущее состояние таймера which
.
int setitimer(int which, struct itimerval *new, struct itimerval *old);
Устанавливает таймер which
на значение new и заменяет old
предыдущей установкой, если она не равна NULL
.
Если параметр таймера it_value
приравнять к нулю, он немедленно заблокируется. Ввод нулевого значения для it_interval
отключает таймер после следующего запуска.
В следующем примере родительский процесс активизирует дочерний процесс, запускает односекундный таймер ITIMER_REAL
, засыпает на 10 секунд, а затем уничтожает дочерний процесс.
1: /* itimer.c */
2:
3: #include <stdio.h>
4: #include <stdlib.h>
5: #include <sys/wait.h>
6: #include <unistd.h>
7: #include <string.h>
8: #include <signal.h>
9: #include <sys/time.h>
10:
11:
12: void catch_signal(int ignored) {
13: static int iteration=0;
14:
15: printf("получен сигнал интервального таймера, итерация %dn",
16: iteration++);
17: }
18:
19: pid_t start_timer(int interval) {
20: pid_t child;
21: struct itimerval it;
22: struct sigaction sa;
23:
24: if (!(child = fork())) {
25: memset(&sa, 0, sizeof(sa));
26: sa.sa_handler = catch_signal;
27: sigemptyset(&sa.sa_mask);
28: sa.sa_flags = SA_RESTART;
29:
30: sigaction(SIGALRM, &sa, NULL);
31:
32: memset(&it, 0, sizeof(it));
33: it.it_interval.tv_sec = interval;
34: it.it_value.tv_sec = interval;
35: setitimer(ITIMER_REAL, &it, NULL);
36:
37: while (1) pause();
38: }
39:
40: return child;
41: }
42:
43: void stop_timer(pid_t child) {
44: kill(child, SIGTERM);
45: }
46:
47: int main (int argc, const char **argv) {
48: pid_t timer = 0;
49:
50: printf("Демонстрация интервальных таймеров для 10 секунд, "
51: "ожидайте...n");
52: timer = start_timer(1);
53: sleep(10);
54: stop_timer(timer);
55: printf("Готово.n");
56:
57: return 0;
58: }
- 14.3.3. Интервальные таймеры: setitimer() и getitimer()
- Таймеры
- Часы и таймеры
- Совет 5. Используйте интервальные функции вместо одноэлементных
- Глава 10 Таймеры и управление временем
- Аппаратные часы и таймеры
- Таймеры ожидания
- 6.2.4. Таймеры, задержки и буферы
- 14.1. Таймеры
- Часы, таймеры и периодические уведомления