• Воспользоваться полем si_overrun из структуры siginfo_t, принятой вместе с сигналом. Такой подход является более экономным по сравнению с вызовом timer_getoverrun(), но это нестандартное решение, доступное только в Linux.

Счетчик дополнительных срабатываний сбрасывается при каждой доставке сигнала. Если с момента обработки или приема сигнала таймер сработает лишь раз, счетчик будет равен 0 (что говорит об отсутствии дополнительных срабатываний).

#define _POSIX_C_SOURCE 199309

#include

int timer_getoverrun(timer_t timerid);

Возвращает количество дополнительных срабатываний при успешном завершении или –1, если произошла ошибка

Функция timer_getoverrun() возвращает количество дополнительных срабатываний таймера, указанного в аргументе timerid. Согласно стандарту SUSv3 она является безопасной для работы с асинхронными сигналами (см. табл. 21.1), поэтому ее можно вызывать внутри обработчика.

23.6.7. Уведомление с помощью потока

Флаг SIGEV_THREAD позволяет программе получать уведомления о срабатывании таймера путем вызова функции в отдельном потоке. Для понимания этого флага нужно иметь представление о POSIX-потоках, с которыми вы познакомитесь позже, в главах 29 и 30. Возможно, вам придется прочитать эти главы, прежде чем переходить к демонстрационной программе, представленной в данном разделе.

Применение флага SIGEV_THREAD показано в листинге 23.7. Эта программа принимает те же аргументы командной строки, что и пример из листинга 23.5, и выполняет следующие шаги.

• Создает и запускает для каждого аргумента командной строки отдельный POSIX-таймер, который использует SIGEV_THREAD в качестве механизма уведомления .

• При каждом срабатывании таймера в отдельном потоке вызывается функция, указанная в поле sev.sigev_notify_function . Она принимает в качестве аргумента значение поля sev.sigev_value.sival_ptr, в котором задан адрес идентификатора таймера (tidlist[j]) . Таким образом, функция уведомления может определить таймер, который инициировал ее вызов.

• Создав и запустив все таймеры, программа входит в цикл и ждет, когда они сработают . На каждой итерации цикла делается вызов pthread_cond_wait(), который ждет оповещения условной переменно (cond) со стороны потока, отвечающего за уведомления таймера.

• При каждом срабатывании таймера вызывается функция threadFunc() . После вывода сообщения она инкрементирует значение глобальной переменной expireCnt, а также добавляет результат, возвращенный вызовом timer_getoverrun(), чтобы учесть возможность дополнительных срабатываний (в подразделе 23.6.6 дополнительные срабатывания рассматривались в контексте механизма уведомлений SIGEV_SIGNAL, однако они возможны и при использовании SIGEV_THREAD, так как перед вызовом соответствующей функции таймер может успеть сработать несколько раз). Функция, доставляющая уведомления, также оповещает условную переменную cond, чтобы главная программа смогла удостовериться в срабатывании таймера .

Программа из листинга 23.7 демонстрируется в следующей сессии командной строки. В этом примере создается два таймера, у которых совпадают начальное время срабатывания и интервал: у одного это 5 секунд, а у второго — 10.

$ ./ptmr_sigev_thread 5:5 10:10

Timer ID: 134525024 (5:5)

Timer ID: 134525080 (10:10)

[13:06:22] Thread notify

timer ID=134525024

timer_getoverrun()=0

main(): count = 1

[13:06:27] Thread notify

timer ID=134525080

timer_getoverrun()=0

main(): count = 2

[13:06:27] Thread notify

timer ID=134525024

timer_getoverrun()=0

main(): count = 3

Нажимаем Ctrl+Z, чтобы приостановить процесс

[1]+ Stopped./ptmr_sigev_thread 5:5 10:10

$ fg Возобновляем выполнение

./ptmr_sigev_thread 5:5 10:10

[13:06:45] Thread notify

timer ID=134525024

timer_getoverrun()=2 Обнаружены дополнительные срабатывания

main(): count = 6

[13:06:45] Thread notify

timer ID=134525080

timer_getoverrun()=0

main(): count = 7

Нажимаем Ctrl+C, чтобы завершить программу

Листинг 23.7. Уведомления POSIX-таймеров на основе функции в отдельном потоке

timers/ptmr_sigev_thread.c

#include

#include

#include

#include "curr_time.h" /* Объявление currTime() */

#include "tlpi_hdr.h"

#include "itimerspec_from_str.h" /* Объявляет itimerspecFromStr() */

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

static int expireCnt = 0; /* Количество срабатываний всех таймеров */

static void /* Функция уведомления в отдельном потоке */

threadFunc(union sigval sv)

{

timer_t *tidptr;

int s;

tidptr = sv.sival_ptr;

printf("[%s] Thread notify\n", currTime("%T"));

printf(" timer ID=%ld\n", (long) *tidptr);

printf(" timer_getoverrun()=%d\n", timer_getoverrun(*tidptr));

/* Инкрементируем счетчик, разделяемый с главным потоком, и оповещаем

Перейти на страницу:

Похожие книги