39 /* обработать оставшиеся данные, вывод диагностики для иллюстрации */
40 printf("I'm glad you are being cooperative.\n");
41 } else
42 printf("\nEOF, eh? We won't give up so easily'\n");
43
44 exit(0);
45 }
Строки 10–18 представляют обработчик сигнала для
SIGALRM
; вызов
assert
гарантирует, что обработчик сигнала был установлен соответствующим образом. Тело обработчика выводит сообщение и выходит, но оно может делать что-нибудь более подходящее для крупномасштабной программы.
В функции
main
строки 27–28 очищают два члена
struct timeval
структуры
struct itimerval.tval
. Затем строка 30 устанавливает тайм-аут в 10 секунд. Установка
tval.it_interval
в 0 означает, что нет повторяющегося сигнала; он срабатывает лишь однажды. Строка 32 устанавливает обработчик сигнала, а строка 34 выводит приглашение.
Строка 36 устанавливает таймер, а строки 37–42 выводят соответствующие сообщения, основываясь на действиях пользователя. Реальная программа выполняла бы в этот момент свою задачу. Важно здесь обратить внимание на строку 38, которая отменяет таймер, поскольку были введены действительные данные.
ЗАМЕЧАНИЕ. Между строками 37 и 38 имеется намеренное состояние гонки. Все дело в том, что если пользователь не вводит строку в течение отведенного таймером времени, будет доставлен сигнал, и обработчик сигнала выведет сообщение «you lose».
Вот три успешных запуска программы:
$ ch14-timers /* Первый запуск, ничего не вводится */
You have ten seconds to enter
your name, rank, and serial number:
*** Timer expired, you lose ***
$ ch14-timers /* Второй запуск, ввод данных */
You have ten seconds to enter
your name, rank, and serial number: Jamas Kirk, Starfleet Captain, 1234
I'm glad you are being cooperative.
$ ch14-timers /* Третий запуск, ввод EOF (^D) */
You have ten seconds to enter
your name, rank, and serial number: ^D
EOF, eh? We won't give up so easily!
POSIX оставляет неопределенным, как интервальные таймеры взаимодействуют с функцией
sleep
, если вообще взаимодействуют. GLIBC не использует для реализации
sleep
функцию
alarm
, поэтому на системах GNU/Linux
sleep
не взаимодействует с интервальным таймером. Однако, для переносимых программ, вы не можете делать такое предположение.
14.3.4. Более точные паузы:
nanosleep
Функция
sleep
(см. раздел 10.8.1 «Сигнальные часы:
sleep
,
alarm
и
SIGALRM
») дает программе возможность приостановиться на указанное число секунд. Но, как мы видели, она принимает лишь целое число секунд, что делает невозможным задержки на короткие периоды, она потенциально может также взаимодействовать с обработчиками