• Аргумент mode представляет собой битовую маску, которая определяет права доступа для новой очереди сообщений. Можно указывать те же битовые значения, что и для файлов (см. табл. 15.4; кроме того, как и в случае с вызовом open(), к маске mode применяется атрибут umask (см. подраздел 15.4.6). Чтобы читать из очереди (mq_receive()), соответствующий класс пользователей должен получить права для чтения; для передачи данных в очередь (mq_send()) требуются права на запись.
• Аргумент attr представляет собой структуру mq_attr, определяющую атрибуты новой очереди сообщений. Если он равен NULL, то очередь создается с атрибутами по умолчанию, которые действуют в текущей системе. Мы опишем структуру mq_attr в разделе 48.4.
В случае успешного выполнения функция mq_open() возвращает
Образец применения функции mq_open() показан в листинге 48.2.
Во время вызова fork() дочерний процесс получает копии дескрипторов очередей сообщений, открытых его родителем, и эти дескрипторы ссылаются на те же очереди (подробней о дескрипторах очередей сообщений речь пойдет в разделе 48.3). Потомок не наследует от родителя подписки на уведомления о сообщениях.
Когда процесс выполняет вызов exec() или завершается, все дескрипторы открытых им очередей сообщений закрываются. В результате этого все подписки процесса на оповещения о поступлении сообщений в соответствующие очереди отменяются.
Функция mq_close() закрывает дескриптор очереди сообщений mqdes.
#include
int mq_close(mqd_t
Возвращает 0 при успешном завершении или -1 при ошибке
Если вызывающий процесс подписался на оповещения о поступлении сообщений в очередь с помощью дескриптора mqdes (см. раздел 48.6), то подписка автоматически удаляется; позже другой процесс сможет подписаться на оповещения из той же очереди.
Дескриптор очереди сообщений автоматически закрывается при завершении процесса или вызове exec(). По аналогии с файловыми, дескрипторы очередей сообщений, которые больше не нужны, следует закрывать вручную, чтобы не столкнуться с проблемой превышения ограничения на количество открытых дескрипторов.
Закрывая очередь сообщений, мы ее не удаляем (точно так же, как, вызывая close(), мы не удаляем сам файл). Для удаления очередей предусмотрена функция mq_unlink(), аналогичная вызову unlink().
Функция mq_unlink() удаляет очередь сообщений с именем name и делает ее кандидатом на уничтожение, которое произойдет, когда ее перестанут использовать все процессы (это может случиться немедленно, если все процессы, открывавшие данную очередь, уже успели ее закрыть).
#include
int mq_unlink(const char *
Возвращает 0 при успешном завершении или -1 при ошибке
Пример использования функции mq_unlink() показан в листинге 48.1.
Листинг 48.1. Применение функции mq_unlink() для удаления очереди POSIX-сообщений
pmsg/pmsg_unlink.c
#include
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
if (argc!= 2 || strcmp(argv[1], "-help") == 0)
usageErr("%s mq-name\n", argv[0]);
if (mq_unlink(argv[1]) == -1)
errExit("mq_unlink");
exit(EXIT_SUCCESS);
}
pmsg/pmsg_unlink.c
Данная связь аналогична отношениям между файловым дескриптором и самим открытым файлом (см. рис. 5.2). Дескриптор очереди сообщений принадлежит конкретному процессу и ссылается на запись в общесистемной таблице открытых дескрипторов этого типа; данная запись в свою очередь указывает на объект очереди. Эта связь проиллюстрирована на рис. 48.1.
В Linux очереди POSIX-сообщений реализованы в виде индексных дескрипторов (i-node) в виртуальной файловой системе; дескрипторы таких очередей представляют собой файловые дескрипторы (обычные и открытые). Однако с точки зрения стандарта SUSv3 эти аспекты реализации не являются обязательными и неактуальны в некоторых других UNIX-системах. Мы еще вернемся к данному вопросу в разделе 48.7, поскольку Linux предоставляет ряд нестандартных возможностей, основанных на особенностях именно этой реализации.