$ ./mq_notify_thread /mq &
[2] 18160
$ cat /dev/mqueue/mq
QSIZE:7 NOTIFY:2 SIGNO:0 NOTIFY_PID:18160
В Linux дескриптор очереди сообщений на самом деле является файловым дескриптором. Для его отслеживания можно задействовать мультиплексирующие системные вызовы ввода/вывода (select() и poll()) или программный интерфейс epoll (подробности о нем см. в главе 59). Это позволяет избежать трудностей, с которыми можно столкнуться при работе с очередями сообщений в System V, когда программа ожидает ввода как в очереди, так и в файловом дескрипторе. Однако данная возможность является нестандартной; спецификация SUSv3 не требует, чтобы дескрипторы очередей сообщений были реализованы в виде файловых дескрипторов.
В стандарте SUSv3 предусмотрено два ограничения, относящихся к очередям сообщений:
• MQ_PRIO_MAX — это ограничение определяет максимально возможный приоритет сообщения. Мы рассматривали его в подразделе 48.5.1;
• MQ_OPEN_MAX — система может установить данное ограничение для определения максимального количества очередей сообщений, доступных для открытия каждому отдельному процессу. Стандарт SUSv3 требует, чтобы это ограничение было равно как минимум _POSIX_MQ_OPEN_MAX (8). В Linux такое ограничение не определено. Вместо него применяется ограничение относительно количества файловых дескрипторов, которые, как вы уже знаете, представляют дескрипторы очередей сообщений (см. раздел 48.7). Иными словами, в Linux общесистемное ограничение и ограничение для отдельных процессов обозначают суммарное количество дескрипторов файлов и очередей сообщений. Больше подробностей о соответствующих ограничениях приводится в разделе 36.3, посвященном ограничению на ресурсы RLIMIT_NOFILE.
Помимо вышеупомянутых ограничений, описанных в стандарте SUSv3, Linux предоставляет несколько файлов внутри /proc, предназначенных для просмотра и (при наличии подходящих привилегий) изменения ограничений, относящихся к использованию очередей сообщений POSIX. Следующие три файла хранятся в каталоге /proc/sys/fs/mqueue.
• msg_max — определяет максимальное значение атрибута mq_maxmsg для новых очередей сообщений (то есть максимум для поля attr.mq_maxmsg, которое применяется при создании очереди с помощью mq_open()). Значение по умолчанию для данного ограничения — 10. Минимальное равно 1 (в ядрах Linux до версии 2.6.28 оно равнялось 10), а максимальное определяется константой HARD_MSGMAX. Ее значение вычисляется по формуле (131,072 / sizeof(void *)) и на платформе Linux/x86-32 равно 32 768. Когда привилегированный процесс (CAP_SYS_RESOURCE) вызывает mq_open(), ограничение msg_max игнорируется, но значение HARD_MSGMAX по-прежнему остается максимальным для поля attr.mq_maxmsg.
• msgsize_max — определяет максимальное значение атрибута mq_msgsize для новых очередей сообщений, созданных непривилегированными процессами (то есть максимум для поля attr.mq_msgsize, которое используется при создании очереди с помощью mq_open()). Значение по умолчанию для данного ограничения — 8192. Минимальное равно 128 (или 8192 в ядрах Linux до версии 2.6.28), а максимальное — 1 048 576 (или INT_MAX в ядрах Linux до версии 2.6.28). Если функция mq_open() вызывается привилегированным процессом (CAP_SYS_RESOURCE), то данное ограничение игнорируется.
• queues_max — это общесистемное ограничение на количество очередей сообщений, которые можно создать. После достижения данного ограничения очереди сообщений могут создаваться только привилегированными процессами (CAP_SYS_RESOURCE). По умолчанию ограничение равно 256. Его можно изменять в пределах от 0 до INT_MAX.
Linux также представляет ограничение на ресурсы RLIMIT_MSGQUEUE, с помощью которого можно установить максимальный объем памяти, потребляемой всеми очередями сообщений, принадлежащими пользователю с заданным реальным идентификатором (см. раздел 36.3).
Очереди сообщений POSIX позволяют процессам обмениваться отдельными блоками данных (сообщениями). Каждое сообщение обладает целочисленным приоритетом, определяющим его место в очереди (и порядок, в котором оно будет получено).
В [Stevens, 1999] приводится альтернативный взгляд на очереди сообщений POSIX и описывается их реализация в пользовательском пространстве на основе файлов, отображенных в память. Отдельные подробности об очередях сообщений POSIX также доступны в [Gallmeister, 1995].
48.1. Измените программу из листинга 48.5 (pmsg_receive.c) так, чтобы она принимала время ожидания в качестве аргумента командной строки и задействовала функцию mq_timedreceive() вместо mq_receive().