23.6.1. Создание таймера: вызов timer_create()

Функция timer_create() создает новый таймер, который отсчитывает время с помощью часов, указанных в аргументе clockid.

#define _POSIX_C_SOURCE 199309

#include

#include

int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);

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

Аргумент clockid может содержать любое значение, указанное в табл. 23.1 или возвращаемое вызовами clock_getcpuclockid() или pthread_getcpuclockid(). Аргумент timerid указывает на буфер с идентификатором, который позволяет обращаться к таймеру в последующих вызовах. Этот буфер имеет тип timer_t, который предусмотрен стандартом SUSv3 для представления идентификаторов таймера.

Аргумент evp определяет то, каким образом программа будет уведомлена о срабатывании таймера. Он указывает на структуру типа sigevent, которая имеет следующий вид:

union sigval {

int sival_int; /* Целочисленное значение для вспомогательных данных */

void *sival_ptr; /* Указатель на вспомогательные данные */

};

struct sigevent {

int sigev_notify; /* Тип уведомления */

int sigev_signo; /* Сигнал о срабатывании таймера */

union sigval sigev_value; /* Значение, сопровождающее сигнал

или передаваемое в функцию потока */

union {

pid_t _tid; /* Идентификатор потока, который получит сигнал /

struct {

void (*_function) (union sigval);

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

void *_attribute; /* Имеет тип 'pthread_attr_t *' */

} _sigev_thread;

} _sigev_un;

};

#define sigev_notify_function _sigev_un._sigev_thread._function

#define sigev_notify_attributes _sigev_un._sigev_thread._attribute

#define sigev_notify_thread_id _sigev_un._tid

Поле sigev_notify этой структуры может принимать одно из значений, перечисленных в табл. 23.2.

Таблица 23.2. Значения поля sigev_notify структуры sigevent

Значение sigev_notify — Тип уведомления — SUSv3

SIGEV_NONE — Без уведомления; отслеживание таймера с помощью timer_gettime() — *

SIGEV_SIGNAL — Отправляет процессу сигнал sigev_signo — *

SIGEV_THREAD — Начинает выполнение нового потока с функции sigev_notify_function — *

SIGEV_THREAD_ID — Отправляет сигнал sigev_signo потоку sigev_notify_thread_id

Ниже подробно описываются константы sigev_notify и поля структуры sigval, связанные с каждой из них.

• SIGEV_NONE — не отправляет уведомление о срабатывании таймера. Процесс по-прежнему может отслеживать состояние таймера с помощью вызова timer_gettime().

• SIGEV_SIGNAL — при срабатывании таймера шлет процессу сигнал, указанный в поле sigev_signo. Если это сигнал реального времени, сопутствующие данные, которые передаются вместе с ним (см. подраздел 22.8.1), должны быть указаны в поле sigev_value (это может быть целое число или указатель). Эти данные можно получить из поля si_value структуры siginfo_t, которая передается обработчику сигнала или возвращается вызовами sigwaitinfo() и sigtimedwait().

• SIGEV_THREAD — при срабатывании таймера вызывает функцию, указанную в поле sigev_notify_function. Эта функция запускается так, как будто она является начальной для нового потока. Слова «как будто» используются в самом стандарте SUSv3; это позволяет реализации генерировать уведомление для периодического таймера двумя способами: либо доставляя каждое из них отдельному новому потоку, либо передавая в единый поток все имеющиеся уведомления. Поле sigev_notify_attributes может содержать либо значение NULL, либо указатель на структуру pthread_attr_t, которая определяет атрибуты потока (см. раздел 29.8). Объединение sigval, указанное внутри sigev_value, передается в функцию в виде единственного аргумента.

• SIGEV_THREAD_ID — похоже на SIGEV_SIGNAL, но сигнал отправляется потоку, чей идентификатор равен sigev_notify_thread_id. Этот поток должен находиться в одном процессе с вызывающим потоком (в случае с SIGEV_SIGNAL сигнал попадает в очередь процесса, и если этот процесс состоит из нескольких потоков, сигнал доставляется одному из них в произвольном порядке). Поле sigev_notify_thread_id может содержать значение, возвращаемое вызовами clone() или gettid(). Флаг SIGEV_THREAD_ID предназначен для использования в потоковых библиотеках (он требует, чтобы при реализации многопоточности был задействован параметр CLONE_THREAD, описанный в подразделе 28.2.1; этому требованию удовлетворяет современная потоковая библиотека NPTL, в отличие от более старой реализации под названием LinuxThreads).

Все вышеперечисленные константы, кроме SIGEV_THREAD_ID (которая доступна только в Linux), входят в стандарт SUSv3.

Аргументу evp можно присвоить значение NULL, тогда результат будет таким же, как если бы мы указали для полей sigev_notify, sigev_signo и sigev_value.sival_int значения SIGEV_SIGNAL, SIGALRM (может варьироваться в зависимости от системы, так как в стандарте SUSv3 сказано лишь «номер сигнала по умолчанию») и соответственно идентификатор таймера.

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

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