pmsg/mq_notify_thread.c
Стоит отметить следующие архитектурные особенности программы из листинга 48.7.
• Программа запрашивает оповещения через поток, указав значение SIGEV_THREAD в поле sigev_notify структуры sigevent, которая передается в функцию mq_notify(). Начальная функция потока, threadFunc(), указана в поле sigev_notify_function
• Включив оповещения, главная программа приостанавливается на неопределенное время; оповещения передаются по таймеру путем вызова в отдельном потоке функции threadFunc()
• Дескриптор очереди сообщений, mqd, можно было бы сделать видимым для функции threadFunc(), создав для него глобальную переменную. Но, чтобы проиллюстрировать альтернативу, мы выбрали другой подход: адрес дескриптора очереди помещается в поле sigev_value.sival_ptr, которое передается вызову mq_notify()
В поле sigev_value.sival_ptr следует хранить не сам дескриптор очереди сообщений (или его версию с приведенным типом), а указатель на него, так как данное значение не является массивом. Кроме того, стандарт SUSv3 не предусматривает никаких гарантий относительно происхождения или размера структуры данных, которая представляет тип mqd_t.
Очереди POSIX-сообщений, реализованные в Linux, предоставляют ряд нестандартных, но полезных возможностей.
В главе 47 мы упоминали: объекты POSIX IPC реализованы в виде файлов, которые хранятся в виртуальной файловой системе, и их можно выводить и удалять с помощью команд ls и rm. Чтобы проделать это с очередями сообщений POSIX, нужно подключить соответствующую файловую систему, используя команду следующего вида:
# mount — t mqueue source target
Параметр source может быть каким угодно (обычно на его месте указывают строку none). Он ни на что не влияет, а всего лишь отображается командами mount и df, которые работают с файлом /proc/mounts. Параметр target — точка подключения файловой системы очереди сообщений. Процесс подключения файловой системы очереди сообщений и вывода ее содержимого показан в следующей сессии командной строки. Для начала создадим каталог и подключим к ней файловую систему:
$ su
Password:
# mkdir /dev/mqueue
# mount — t mqueue none /dev/mqueue
$ exit
Теперь выведем запись файла /proc/mounts, которая касается нового подключения, а также права доступа к точке подключения:
$ cat /proc/mounts | grep mqueue
none /dev/mqueue mqueue rw 0 0
$ ls — ld /dev/mqueue
drwxrwxrwt 2 root root 40 Jul 26 12:09 /dev/mqueue
В выводе команды ls стоит обратить внимание на следующий аспект: при подключении файловой системы очереди сообщений выбранного каталога автоматически устанавливается закрепляющий бит (на это указывает буква t в поле с правами доступа). Это значит, что непривилегированный процесс может отключить только ту очередь, которой он владеет.
В завершение создадим очередь сообщений, выведем ее имя с помощью команды ls и удалим ее:
$ ./pmsg_create — c /newq
$ ls /dev/mqueue
newq
$ rm /dev/mqueue/newq
Можно вывести содержимое объектов в файловой системе очереди сообщений. Каждый из таких объектов (виртуальных файлов) содержит информацию о соответствующей очереди:
$ ./pmsg_create — c /mq
$ ./pmsg_send /mq abcdefg
$ cat /dev/mqueue/mq
QSIZE:7 NOTIFY:0 SIGNO:0 NOTIFY_PID:0
Поле QSIZE обозначает общее количество байтов данных в очереди. Оставшиеся поля относятся к оповещениям. Если значение NOTIFY_PID не равно 0, то процесс с указанным идентификатором подписался на оповещения для этой очереди; сведения о типе оповещений хранятся в следующих полях:
• NOTIFY — значение, связанное с одной из констант sigev_notify: 0 (SIGEV_SIGNAL), 1 (SIGEV_NONE) или 2 (SIGEV_THREAD);
• при выборе типа оповещения SIGEV_SIGNAL поле SIGNO определяет, какой именно сигнал будет доставлен.
Информация, хранящаяся в этих полях, проиллюстрирована в следующей сессии командной строки:
$ ./mq_notify_sig /mq &
$ cat /dev/mqueue/mq
QSIZE:7 NOTIFY:0 SIGNO:10 NOTIFY_PID:18158
$ kill %1
[1] Terminated./mq_notify_sig /mq