switch (opt) {
case 'c':
flags |= O_CREAT;
break;
case 'm':
attr.mq_maxmsg = atoi(optarg);
attrp = &attr
break;
case 's':
attr.mq_msgsize = atoi(optarg);
attrp = &attr
break;
case 'x':
flags |= O_EXCL;
break;
default:
usageError(argv[0]);
}
}
if (optind >= argc)
usageError(argv[0]);
perms = (argc <= optind + 1)? (S_IRUSR | S_IWUSR):
getInt(argv[optind + 1], GN_BASE_8, "octal-perms");
mqd = mq_open(argv[optind], flags, perms, attrp);
if (mqd == (mqd_t) -1)
errExit("mq_open");
exit(EXIT_SUCCESS);
}
pmsg/pmsg_create.c
Функция mq_getattr() возвращает структуру mq_attr, содержащую сведения об атрибутах очереди сообщений и саму очередь, связанную с дескриптором mqdes.
#include
int mq_getattr(mqd_t
Возвращает 0 при успешном завершении или -1 при ошибке
Помимо полей mq_maxmsg и mq_msgsize, уже описанных выше, возвращенная структура, на которую указывает аргумент attr, содержит следующие поля.
• mq_flags — это флаги для описания открытой очереди сообщений, связанной с дескриптором mqdes. Допускается только один флаг: O_NONBLOCK. Он инициализируется путем аргумента oflag в вызове mq_open() и может быть изменен с помощью функции mq_setattr().
• mq_curmsgs — это количество сообщений, находящихся в очереди на текущий момент. За время с начала вызова mq_getattr() и до его завершения какой-то другой процесс может изменить данный атрибут, прочитав сообщение из очереди или записав его туда.
Программа, представленная в листинге 48.3, использует функцию mq_getattr(), чтобы извлечь атрибуты очереди сообщений, заданные в качестве аргументов командной строки, и затем направляет их в стандартный вывод.
Листинг 48.3. Извлечение атрибутов очереди сообщений POSIX
pmsg/pmsg_getattr.c
#include
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
mqd_t mqd;
struct mq_attr attr;
if (argc!= 2 || strcmp(argv[1], "-help") == 0)
usageErr("%s mq-name\n", argv[0]);
mqd = mq_open(argv[1], O_RDONLY);
if (mqd == (mqd_t) -1)
errExit("mq_open");
if (mq_getattr(mqd, &attr) == -1)
errExit("mq_getattr");
printf("Maximum # of messages on queue: %ld\n", attr.mq_maxmsg);
printf("Maximum message size: %ld\n", attr.mq_msgsize);
printf("# of messages currently on queue: %ld\n", attr.mq_curmsgs);
exit(EXIT_SUCCESS);
}
pmsg/pmsg_getattr.c
В следующей сессии командной строки мы воспользуемся программой из листинга 48.2 для создания очереди сообщений с атрибутами, которые действуют по умолчанию в текущей системе (то есть передадим NULL в качестве последнего аргумента функции mq_open()), а затем выведем эти атрибуты с помощью программы из листинга 48.3. Таким образом мы покажем, какие параметры применяются по умолчанию в Linux.
$ ./pmsg_create — cx /mq
$ ./pmsg_getattr /mq
Maximum # of messages on queue: 10
Maximum message size: 8192
# of messages currently on queue: 0
$ ./pmsg_unlink /mq
По выводу, представленному выше, можно понять, что в Linux стандартными значениями для атрибутов mq_maxmsg и mq_msgsize являются числа 10 и 8192 соответственно.
Эти значения могут сильно варьироваться в зависимости от реализации. Портируемые приложения должны явно указывать данные атрибуты, не полагаясь на стандартные значения.
Функция mq_setattr() устанавливает атрибуты очереди сообщений, связанной с дескриптором mqdes, и в случае необходимости возвращает сведения о самой очереди.
#include
int mq_setattr(mqd_t
struct mq_attr *
Возвращает 0 при успешном завершении или -1 при ошибке
Функция mq_setattr() выполняет следующие действия:
• использует поле mq_flags в структуре mq_attr, на которую указывает аргумент newattr, чтобы изменить флаги описания очереди сообщений, связанной с дескриптором mqdes;
• если аргумент oldattr не равен NULL, то функция возвращает структуру mq_attr, содержащую предыдущие флаги описания очереди сообщений и ее атрибуты (то есть дублирует работу функции mq_getattr()).
Согласно стандарту SUSv3 функция mq_setattr() может изменить только состояние флага O_NONBLOCK.
Разные системы могут предоставлять другие флаги, доступные для изменения, и, возможно, в будущем в стандарте SUSv3 будут добавлены новые флаги. Учитывая все это, портируемые приложения должны изменять состояние флага O_NONBLOCK в три этапа: сначала извлечь значение mq_flags с помощью функции mq_getattr(), модифицировать бит O_NONBLOCK и затем вызвать mq_setattr() для установки новых параметров mq_flags. Например, чтобы включить O_NONBLOCK, нужно сделать следующее:
if (mq_getattr(mqd, &attr) == -1)
errExit("mq_getattr");
attr.mq_flags |= O_NONBLOCK;
if (mq_setattr(mqd, &attr, NULL) == -1)
errExit("mq_getattr");