SIGRTMIN и SIGRTMAX. Количество таких сигналов определяется в системе константой RTSIG_MAX, которая должна быть не менее 8 (POSIX). В QNX: SIGRTMIN = 41, SIGRTMAX = 56.

2. Обработка сигналов реального времени строится на основе очереди. Если сигнал порожден N раз, то он должен быть и N раз получен адресатом (в описываемых ранее моделях это не так, в них процесс получает только единичный экземпляр сигнала). Повторные экземпляры одного и того же сигнала в модели реального времени доставляются обработчику в порядке FIFO.

3. Помимо 8-битного кода с сигналом реального времени ассоциируется 32-битное значение (si_value, мы им займемся позже), заполняемое отправителем и доставляемое получателю (что позволяет «различать» экземпляры сигналов в очереди, о которой говорилось выше).

4. Для работы с сигналами реального времени добавлено несколько новых функций. В частности, в этой модели для отправки сигнала некоторому процессу используется sigqueue() вместо kill().

Эти два вызова определяются очень близкими формами:

int kill(pid_t pid, int signo);

int sigqueue(pid_t pid, int signo, const union sigval value);

Примечание

Как мы вскоре увидим, эти две синтаксические формы одного и того же вызова отличаются лишь тем, помещают ли они в сигнал указанное значение или оставляют его нулевым. Если процесс устанавливает обработку сигнала на основании очереди, он будет получать почти одинаковым образом сигналы, посланные обоими вызовами. Разница «почти» состоит в том, что получатель на основании анализа поля si_code в siginfo_t в состоянии отличить, каким вызовом ему был послан сигнал.

Примечание

При ошибке выполнения sigqueue() (код возврата -1) могут устанавливаться (в errno) следующие коды ошибок:

• EAGAIN — недостаточно ресурсов для помещения сигнала в очередь;

• EINVAL — недопустимое значение signo или неподдерживаемый сигнал;

• ENOSYS — вызов sigqueue() не поддерживается реализацией (возможно, версией);

• EPERM — у процесса недостаточно привилегий для посылки сигнала принимающему процессу;

• ESRCH — несуществующий PID процесса получателя.

Последний случай особо интересен, так как при указании в качестве номера сигнала signo = 0 реальная посылка сигнала не производится, но устанавливается код ошибки. Это простейший и эффективный способ выяснить, выполняется ли в системе процесс с заданным PID.

5. Когда в очередь помещаются различные не заблокированные процессом (потоком) сигналы в диапазоне SIGRTMINSIGRTMAX, то сигналы с меньшими номерами доставляются обработчику из FIFO-очереди раньше сигналов с большими номерами (то есть сигналы с меньшими номерами имеют более высокий приоритет).

6. Обработчик для сигналов реального времени устанавливается с флагом SA_SIGINFO, а функция обработчика объявляется теперь с другим прототипом:

void func(int signo, siginfo_t* info, void* context);

Обработчик имеет больше параметров и получает больше информации. POSIX требует, чтобы тип siginfo_t содержал как минимум:

typedef struct {

 int si_signo;

 int si_code;

 union sigval si_value; /* целое или указатель от отправителя */

} siginfo_t;

В QNX sigval определяется так (подобное определение дают и другие ОС UNIX):

union sigval {

 int sival_int;

 void *sival_ptr;

};

Это 32-битное значение предназначено для посылки совместно с сигналом данных для получателя, которые, как видно из синтаксиса определения sigval, могут быть целочисленным значением или указателем неспецифицированного типа.

7. Поле si_code типа siginfo_t, передаваемое получателю, определяет природу возбуждения сигнала:

 • SI_ASINCIO — сигнал порожден завершением операций асинхронного ввода/вывода, запущенного одной из функций POSIX aio_*();

 • SI_MESGQ — сигнал возбуждается при помещении сообщения в пустую очередь сообщений UNIX;

 • SI_QUEUE — сигнал был отправлен функцией sigqueue() (в этом разделе нас интересуют только такие сигналы);

 • SI_TIMER — сигнал был порожден по истечении установленного времени интервального таймера;

 • SI_USER — сигнал был отправлен функцией kill().

8. Допускается, что при возбуждении сигнала еще каким-либо механизмом (сверх перечисленных, что может определяться специфическими особенностями ОС) значение si_code может отличаться от перечисленных. Однако значение поля si_value считается актуальным только в тех случаях, когда si_code имеет одно из значений: SI_ASINCIO, SI_MESGQ, SI_QUEUE, SI_TIMER.

9. Согласно POSIX сигналы, обработчики для которых также устанавливаются с флагом SA_SIGINFO, но не входящие в диапазон сигналов реального времени, например стандартные сигналы UNIX, могут обрабатываться как на основе помещения их в очередь, так и без ее использования; выбор оставляется на усмотрение разработчика ОС.

Мы перечислили основные требования POSIX к модели обработки сигналов реального времени. Дополнения, отличия и специфические структуры данных QNX будут рассмотрены немного позже.

Весьма доходчивый пример для проверки и иллюстрации обработки сигналов реального времени приведен У. Стивенсом [2]. Мы же построим приложение, реализующее его основную идею:[33]

Приоритеты сигналов реального времени

#include <stdlib.h>

#include <stdio.h>

#include <iostream.h>

#include <signal.h>

#include <unistd.h>

static void handler(int signo, siginfo_t* info, void* context) {

 cout << 'received signal ' << signo << ' code = ' << info->si_code <<

  ' val = ' << info->si_value.sival_int << endl;

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату