■ Если в поле sa_flags установлен флаг SA_SIGINFO, поле sa_sigaction указывает адрес функции-обработчика сигнала.
■ Если флаг SA_SIGINFO не установлен, поле sa_handler указывает адрес функции-обработчика сигнала.
■ Чтобы сопоставить сигналу действие по умолчанию или игнорировать его, следует установить sa_handler равным либо SIG_DFL, либо SIG_IGN и не устанавливать флаг SA_SIGINFO.
8-17 Мы всегда устанавливаем флаг SA_SIGINFO и указываем флаг SA_RESTART, если перехвачен какой-либо другой сигнал, кроме SIGALRM.
Теперь рассмотрим реализацию очередей сообщений Posix с использованием отображения в память, взаимных исключений и условных переменных Posix.
ПРИМЕЧАНИЕ
Взаимные исключения и условные переменные описаны в главе 7, а ввод-вывод с отображением в память — в главах 12 и 13. Вы можете отложить данный раздел до ознакомления с этими главами.
На рис. 5.2 приведена схема структур данных, которыми мы пользуемся для реализации очереди сообщений Posix. Изображенная очередь может содержать до четырех сообщений по 7 байт каждое.
В листинге 5.16 приведен заголовочный файл mqueue.h, определяющий основные структуры, используемые в этой реализации.
Дескриптор нашей очереди сообщений является просто указателем на структуру mq_infо. Каждый вызов mq_open выделяет память под одну такую структуру, а вызвавшему возвращается указатель на нее. Повторим, что дескриптор очереди сообщений не обязательно является небольшим целым числом, как дескриптор файла — единственное ограничение, накладываемое Posix, заключается в том, что этот тип данных не может быть массивом.
//my_pxmsg_mmap/mqueue.h
1 typedef struct mymq_info *mymqd_t;
2 struct mymq_attr {
3 long mq_flags; /* флаг очереди : O_NONBLOCK */
4 long mq_maxmsg; /* максимальное количество сообщений в очереди */
5 long mq_msgsize; /* максимальный размер сообщения в байтах */
6 long mq_curmsgs; /* количество сообщений в очереди */
7 };
8 /* одна структура mymq_hdr{} на очередь, в начале отображаемого файла */
9 struct mymq_hdr {
10 struct mymq_attr mqh_attr; /* атрибуты очереди */
11 long mqh_head; /* индекс первого сообщения*/
12 long mqh_free; /* индекс первого пустого сообщения */
13 long mqh_nwait; /* количество заблокированных mq_receive() потоков */
14 pid_t mqh_pid; /* ненулевой PID. если включено уведомление */
15 struct sigevent mqh_event; /* для mq_notify() */
16 pthread_mutex_t mqh_lock; /* блокировка: mutex*/
17 pthread_cond_t mqh_wait; /* и условная переменная */
18 };
19 /* один mymsg_hdr{} в начале каждого сообщения */
20 struct mymsg_hdr {
21 long msg_next; /* индекс следующего сообщения в списке */
22 /* msg_next должно быть первым полем в структуре */
23 ssize_t msg_len; /* реальная длина */
24 unsigned int msg_prio; /* приоритет */
25 };
26 /* одна mymq_info{} выделяется при каждом mq_open() */
27 struct mymq_info {
28 struct mymq_hdr *mqi_hdr; /* начало отображаемого файла */
29 long mqi_magic; /* магическое значение после инициализации */
30 int mqi_flags; /* флаги для данного процесса */
31 };
32 #define MQI_MAGIC 0x98765432
33 /* размер сообщения округляется для подгонки */