Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform
Шрифт:
Отметим, что sigev_coid может описывать соединение на любом канале (обычно, хотя и не обязательно, этот канал связан с процессом, который инициирует событие).
Чтобы передать сигнал, укажите в поле
SIGEV_SIGNAL
Процессу будет передан обычный сигнал.
SIGEV_SIGNAL_CODE
Процессу будет передан сигнал, содержащий 8-битный код.
SIGEV_SIGNAL_THREAD
Сигнал, содержащий 8-битный код,
При выборе уведомления типа SIGEV_SIGNAL* нужно будет заполнить ряд дополнительных полей:
Поле | Значение и смысл |
---|---|
sigev_signo | Номер сигнала для передачи (берется из <signal.h> , например, SIGALRM). |
sigev_code | 8-разрядный код (для уведомления типа SIGEV_SIGNAL_CODE или SIGEV_SIGNAL_THREAD). |
Для создания потока по срабатыванию таймера установите поле sigev_notify в значение SIGEV_THREAD и заполните следующие поля:
Поле | Значение и смысл |
---|---|
sigev_notify_function | Адрес функции, возвращающей void* и принимающей void* , которая будет вызвана при возникновении события. |
sigev_value | Значение, которое будет передано функции sigev_notify_function в качестве параметра. |
sigev_notify_attributes | Атрибутная запись потока (см. главу «Процессы и потоки», параграф «Атрибутная запись потока»). |
Этот тип уведомления воистину страшен. Если ваш таймер будет срабатывать слишком часто, и при этом будут готовы к выполнению потоки с более высоким приоритетом, чем вновь создаваемые, то у вас быстро вырастет огромная куча заблокированных потоков, и они съедят все ресурсы вашей машины. Пользуйтесь этим типом уведомления с осторожностью!
В файле
SIGEV_SIGNAL_INIT(eventp, signo)
Установите eventp в SIGEV_SIGNAL и впишите соответствующий номер сигнала signo.
SIGEV_SIGNAL_CODE_INIT(eventp, signo, value, code)
Установите поле eventp в SIGEV_SIGNAL_CODE, укажите номер сигнала в signo, а также задайте значения полей value
SIGEV_SIGNAL_THREAD_INIT(eventp, signo, value, code)
Установите eventp в SIGEV_SIGNAL_THREAD, укажите номер сигнала в signo, а также задайте значения полей value и code.
SIGEV_PULSE_INIT(eventp, coid, priority, code, value)
Установите eventp в SIGEV_SIGNAL_PULSE, укажите идентификатор соединения в coid, а также параметры priority, code и value. Отметьте, что для priority есть специальное значение SIGEV_PULSE_PRIO_INHERIT, которое предотвращает изменение приоритета принимающего потока.
SIGEV_UNBLOCK_INIT(eventp)
Установите eventp в SIGEV_UNBLOCK.
SIGEV_INTR_INIT(eventp)
Установите eventp в SIGEV_INTR.
SIGEV_THREAD_INIT(eventp, func, attributes)
Задайте значения eventp, функции потока func и атрибутной записи attributes.
Предположим, что вы разрабатываете сервер, который будет обречен провести большую часть своей жизни в RECEIVE-блокированном состоянии, ожидая сообщение. Идеальным вариантом здесь было бы принять специальное сообщение, указывающее, что момент, которого мы так долго ждали, наконец настал.
Как раз при таком сценарии и надо использовать импульсы в качестве схемы уведомления. В разделе «Применение таймеров», представленном ниже, я приведу пример кода, который можно использовать для периодического получения импульсов.
Предположим, что, с другой стороны, вы выполняете некоторую работу, но не желаете, чтобы она продолжалась вечно. Например, вы ожидаете возврата из некоторой функции, но не можете точно предсказать, сколько времени на это потребуется.
В этом случае оправданным выбором является использование уведомления при помощи сигнала — возможно, даже с обработчиком. (Другой вариант, который мы обсудим позже, заключается в использовании тайм-аутов ядра; см. также параграф «_NTO_CHF_UNBLOCK» в главе «Обмен сообщениями»). В параграфе «Применение таймеров», представленном ниже, мы рассмотрим пример, использующий сигналы.
Если вы вообще не собираетесь принимать сообщения, то использование сигнала и функции sigwait является более экономной альтернативой созданию канала для принятия импульсного сообщения.
Применение таймеров
Изучив все красоты теории, давайте теперь переключим наше внимание на конкретные образцы кода, чтобы посмотреть, что можно сделать при помощи таймеров.
Чтобы работать с таймером, вам потребуется: