Рейтинговые книги
Читем онлайн QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 40 41 42 43 44 45 46 47 48 ... 106

Как и большинство сигнальных функций, данная функция возвращает нулевое значение в результате успешного выполнения и -1 в случае неудачи, при этом код ошибки устанавливается в errno.

Именно эта функция снимает одно из самых существенных ограничений, свойственных модели «ненадежных сигналов», — позволяет заблокировать реакцию на сигналы при выполнении критических участков кода и восстановить ее при завершении выполнения этих участков.

Модель сигналов реального времени

Сигналы реального времени были добавлены в POSIX относительно недавно (1996 г.). Эта новая модель в различных ОС UNIX реализуется с разной степенью полноты и с отклонениями от спецификаций, и QNX не исключение. Модель еще до конца не отработана, поэтому возможны сюрпризы (и сейчас они будут).

Модель сигналов реального времени, которую специфицирует POSIX, устанавливается флагом SA_SIGINFO(который уже упоминался выше) при вызове sigaction(). В нижеследующем перечислении того, что предусматривает эта модель, мы излагаем в первую очередь качественную картину происходящего, предлагаемую POSIX, кое-где уточняя ее конкретными данными реализации QNX (артефакты в поведении QNX будут отдельно отмечены позже):

1. Сигналы, называемые сигналами реального времени, могут принимать значения между 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. Когда в очередь помещаются различные не заблокированные процессом (потоком) сигналы в диапазоне SIGRTMIN… SIGRTMAX, то сигналы с меньшими номерами доставляются обработчику из 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.

1 ... 40 41 42 43 44 45 46 47 48 ... 106
На этой странице вы можете бесплатно читать книгу QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович бесплатно.

Оставить комментарий