Таймер, работу которого мы только что обсудили, называют
А что если вы захотите сделать что-нибудь полезное, пока поток ожидает наступления установленной даты? Или делать что-либо и получать «синхроимпульс» каждые 27 секунд? Здесь нельзя просто так позволить себе спать!
Как мы уже обсуждали в главе «Процессы и потоки», вы можете просто запустить другой поток, и пусть он выполняет работу, пока ваш поток спит. Однако, поскольку мы говорим сейчас о таймерах, посмотрим, как это можно сделать другим способом.
В зависимости от выбранной цели, вы можете сделать это с помощью либо периодического, либо однократного таймера.
Реализация этих таймеров в ядре основана на том же самом принципе, что и в случае с таймером задержки из нашего первого примера. Ядро запоминает абсолютное значение времени (если вы укажете сделать именно так) и хранит его. Обработчик прерываний таймера сравнивает сохраненное значение времени с текущим.
Однако, вместо удаления из очереди на выполнение после системного вызова, на этот раз ваш поток продолжит работу. И в момент, когда суточное время достигнет заданного вами и хранимого в памяти момента времени, ядро уведомит ваш поток о том, что назначенное время пришло.
Схема уведомления
Как получить уведомление о тайм-ауте? При использовании таймера задержки вы получаете уведомление просто посредством возвращения в состояние READY.
При использовании периодически и однократных таймеров у вас появляется выбор:
• послать импульс;
• послать сигнал:
• создать поток.
Импульсы мы уже обсуждали главе «Обмен сообщениями»; сигналы — стандартный для UNIX механизм. Здесь же мы кратко рассмотрим уведомления при помощи создания потока.
Независимо от выбранной вами схемы уведомления, вам обязательно придется заполнять структуру struct sigevent
. Давайте вкратце посмотрим, как это делается.
struct sigevent {
int sigev_notify;
union {
int sigev_signo;
int sigev_coid;
int sigev_id;
void (*sigev_notify_function)(union sigval);
};
union sigval sigev_value;
union {
struct {
short sigev_code;
short sigev_priority;
};
pthread_attr_t *sigev_notify_attributes;
};
};
#define
, которая заставляет именованные объединения и структуры выглядеть неименованными. Подробнее см.
.
Первое поле, которое вы должны заполнить, — это элемент
SIGEV_PULSE
Будет передан импульс.
SIGEV_SIGNAL, SIGEV_ SIGNAL _CODE или SIGEV_SIGNAL_THREAD
Будет передан сигнал.
SIGEV_UNBLOCK
В данном случае не используется; предназначен для тайм-аутов ядра (см. ниже в разделе «Тайм-ауты ядра»).
SIGEV_INTR
В данном случае не используется; предназначен для прерываний (см. главу «Прерывания»),
SIGEV_THREAD
Будет создан поток.
Поскольку мы намерены использовать структуру struct sigevent
для таймеров, нас будут интересовать только такие значения
Чтобы передать импульс при срабатывании таймера, присвойте полю