Рис. 48.1.
Рисунок 48.1 помогает прояснить пару моментов относительно использования дескрипторов очередей сообщений (каждый из которых является аналогом файлового дескриптора).
• Описание открытой очереди сообщений содержит набор флагов. Стандарт SUSv3 предусматривает только один такой флаг, O_NONBLOCK, определяющий, должен ли ввод/вывод быть неблокирующим.
• Два разных процесса могут обладать дескрипторами (на диаграмме обозначены как x), которые ссылаются на одно и то же описание открытой очереди сообщений. Это может произойти, если процесс вызовет fork() после открытия очереди. Такие дескрипторы разделяют состояние флага O_NONBLOCK.
• Два разных процесса могут обладать открытыми дескрипторами, ссылающимися на разные описания, связанные с одной и той же очередью сообщений (например, дескриптор z в процессе А и дескриптор y в процессе Б ссылаются на /mq-r). Это происходит в ситуации, когда оба процесса задействуют функцию mq_open() для открытия одной и той же очереди.
Каждая из трех функций — mq_open(), mq_getattr() и mq_setattr() — принимает аргумент, который является указателем на структуру mq_attr. Она определена в заголовочном файле
struct mq_attr {
long mq_flags; /* Флаги описания очереди сообщений: 0 или
O_NONBLOCK [mq_getattr(), mq_setattr()] */
long mq_maxmsg; /* Максимальное количество сообщений в
очереди [mq_open(), mq_getattr()] */
long mq_msgsize; /* Максимальный размер сообщения (в байтах)
[mq_open(), mq_getattr()] */
long mq_curmsgs; /* Количество сообщений в очереди на текущий
момент [mq_getattr()] */
};
Прежде чем приступить к подробному рассмотрению структуры mq_attr, необходимо отметить следующее.
• Только часть этих полей используется всеми тремя функциями. Функции, в которых применяется каждое из полей, обозначены в комментариях к определению структуры (см. выше).
• Структура содержит сведения об описании открытой очереди сообщений (mq_flags), связанной с дескриптором сообщения и информацией об очереди, на которую тот ссылается (mq_maxmsg, mq_msgsize, mq_curmsgs).
• Часть полей содержит информацию, записанную на момент создания очереди с помощью функции mq_open() (mq_maxmsg и mq_msgsize); в других хранятся сведения о текущем состоянии описания открытой очереди сообщений (mq_flags) или о самой очереди (mq_curmsgs).
При создании очереди сообщений с помощью вызова mq_open() ее атрибуты определяются следующими полями структуры mq_attr:
• поле mq_maxmsg определяет максимальное количество сообщений, которое можно поместить в очередь, используя вызов mq_send(). Это значение должно быть больше 0;
• поле mq_msgsize определяет максимальный размер каждого сообщения, которое может оказаться в очереди. Это значение тоже должно быть больше 0.
Вместе оба поля позволяют ядру определить максимальный объем памяти, который может потребоваться для данной очереди сообщений.
Атрибуты mq_maxmsg и mq_msgsize инициализируются во время создания очереди и больше не могут быть изменены. В разделе 48.8 мы опишем два файла в каталоге /proc, устанавливающие общесистемное ограничение на значения, которые можно присвоить атрибутам mq_maxmsg и mq_msgsize.
Программа из листинга 48.2 предоставляет интерфейс командной строки к функции mq_open() и демонстрирует применение структуры mq_attr.
Чтобы задать атрибуты очереди сообщений, предусмотрено два параметра командной строки: — m для mq_maxmsg и — s для mq_msgsize. При указании любого из них функции mq_open() будет передан ненулевой аргумент attrp. Полям структуры mq_attr, на которую указывает этот аргумент, по умолчанию присваиваются некие значения (при условии, что был указан только один из параметров командной строки). Если ни один из параметров не указан, то функции mq_open() в качестве аргумента attrp передается значение NULL. В таком случае очередь сообщений создается с атрибутами, применяемыми по умолчанию в текущей системе.
Листинг 48.2. Создание очереди сообщений POSIX
pmsg/pmsg_create.c
#include
#include
#include
#include "tlpi_hdr.h"
static void
usageError(const char *progName)
{
fprintf(stderr, "Usage: %s [-cx] [-m maxmsg] [-s msgsize] mq-name "
"[octal-perms]\n", progName);
fprintf(stderr, " — c Create queue (O_CREAT)\n");
fprintf(stderr, " — m maxmsg Set maximum # of messages\n");
fprintf(stderr, " — s msgsize Set maximum message size\n");
fprintf(stderr, " — x Create exclusively (O_EXCL)\n");
exit(EXIT_FAILURE);
}
int
main(int argc, char *argv[])
{
int flags, opt;
mode_t perms;
mqd_t mqd;
struct mq_attr attr, *attrp;
attrp = NULL;
attr.mq_maxmsg = 10;
attr.mq_msgsize = 2048;
flags = O_RDWR;
/* Разбираем параметры командной строки */
while ((opt = getopt(argc, argv, "cm: s: x"))!= -1) {