Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
struct itimerval { struct timeval it_interval; /* следующее значение */ struct timeval it_value; /* текущее значение */};Прикладным программам не следует ожидать, что таймеры будут с точностью до микросекунд. Справочная страница getitimer(2) дает следующее объяснение:
Таймеры никогда не срабатывают раньше заданного времени, вместо этого срабатывая спустя небольшой постоянный интервал времени, зависящий от разрешения системного таймера (в настоящее время 10 мс). После срабатывания будет сгенерирован сигнал, а таймер будет сброшен. Если таймер срабатывает, когда процесс выполняется (для таймера
ITIMER_VIRTИз этих трех таймеров
ITIMER_REALch14-timers.c1 /* ch14-timers.c --- демонстрация интервальных таймеров */23 #include <stdio.h>4 #include <assert.h>5 #include <signal.h>6 #include <sys/time.h>78 /* handler --- обрабатывает SIGALRM */910 void handler(int signo)11 {12 static const char msg[] = "n*** Timer expired, you lose ***n";1314 assert(signo == SIGALRM);1516 write(2, msg, sizeof(msg) - 1);17 exit(1);18 }1920 /* main --- установить таймер, прочесть данные с тайм-аутом */2122 int main(void)23 {24 struct itimerval tval;25 char string[BUFSIZ];2627 timerclear(&tval.it_interval); /* нулевой интервал означает не сбрасывать таймер */28 timerclear(&tval.it_value);2930 tval.it_value.tv_sec = 10; /* тайм-аут 10 секунд */3132 (void)signal(SIGALRM, handler);333435 printf("You have ten seconds to enternyour name, rank, and serial number: ");36 (void)setitimer(ITIMER_REAL, &tval, NULL);37 if (fgets(string, sizeof string, stdin) != NULL) {38 (void)setitimer(ITIMER_REAL, NULL, NULL); /* выключить таймер */39 /* обработать оставшиеся данные, вывод диагностики для иллюстрации */40 printf("I'm glad you are being cooperative.n");41 } else42 printf("nEOF, eh? We won't give up so easily'n");4344 exit(0);45 }Строки 10–18 представляют обработчик сигнала для
SIGALRMassert()В функции
main()struct timevalstruct itimerval.tvaltval.it_intervalСтрока 36 устанавливает таймер, а строки 37–42 выводят соответствующие сообщения, основываясь на действиях пользователя. Реальная программа выполняла бы в этот момент свою задачу. Важно здесь обратить внимание на строку 38, которая отменяет таймер, поскольку были введены действительные данные.
ЗАМЕЧАНИЕ. Между строками 37 и 38 имеется намеренное состояние гонки. Все дело в том, что если пользователь не вводит строку в течение отведенного таймером времени, будет доставлен сигнал, и обработчик сигнала выведет сообщение «you lose».
Вот три успешных запуска программы:
$ <b>ch14-timers</b> /* Первый запуск, ничего не вводится */You have ten seconds to enteryour name, rank, and serial number:*** Timer expired, you lose ***$ <b>ch14-timers</b> /* Второй запуск, ввод данных */You have ten seconds to enteryour name, rank, and serial number: <b>Jamas Kirk, Starfleet Captain, 1234</b>I'm glad you are being cooperative.$ <b>ch14-timers</b> /* Третий запуск, ввод EOF (^D) */You have ten seconds to enteryour name, rank, and serial number: <b>^D</b>EOF, eh? We won't give up so easily!POSIX оставляет неопределенным, как интервальные таймеры взаимодействуют с функцией
sleep()sleep()alarm()sleep()