$ ./pmsg_send /mq msg-b 0

$ ./pmsg_send /mq msg-c 10

Затем последовательно выполним несколько команд, чтобы извлечь эти сообщения из очереди:

$ ./pmsg_receive /mq

Read 5 bytes; priority = 10

msg-c

$ ./pmsg_receive /mq

Read 5 bytes; priority = 5

msg-a

$ ./pmsg_receive /mq

Read 5 bytes; priority = 0

msg-b

Как видно из вывода, приведенного выше, сообщения были извлечены в порядке их приоритета.

На этот момент очередь является пустой. Если выполнить еще одно блокирующее извлечение, то операция будет приостановлена:

$ ./pmsg_receive /mq

Блокируется; чтобы завершить программу, нажимаем Ctrl+C

С другой стороны, если выполнить неблокирующее извлечение, то вызов немедленно вернет сообщение об ошибке:

$ ./pmsg_receive — n /mq

ERROR [EAGAIN/EWOULDBLOCK Resource temporarily unavailable] mq_receive

Листинг 48.5. Чтение сообщений из очереди POSIX

pmsg/pmsg_receive.c

#include

#include  /* Для определения O_NONBLOCK */

#include "tlpi_hdr.h"

static void

usageError(const char *progName)

{

fprintf(stderr, "Usage: %s [-n] mq-name\n", progName);

fprintf(stderr, " — n Use O_NONBLOCK flag\n");

exit(EXIT_FAILURE);

}

int

main(int argc, char *argv[])

{

int flags, opt;

mqd_t mqd;

unsigned int prio;

void *buffer;

struct mq_attr attr;

ssize_t numRead;

flags = O_RDONLY;

while ((opt = getopt(argc, argv, "n"))!= -1) {

switch (opt) {

case 'n': flags |= O_NONBLOCK; break;

default: usageError(argv[0]);

}

}

if (optind >= argc)

usageError(argv[0]);

mqd = mq_open(argv[optind], flags);

if (mqd == (mqd_t) -1)

errExit("mq_open");

if (mq_getattr(mqd, &attr) == -1)

errExit("mq_getattr");

buffer = malloc(attr.mq_msgsize);

if (buffer == NULL)

errExit("malloc");

numRead = mq_receive(mqd, buffer, attr.mq_msgsize, &prio);

if (numRead == -1)

errExit("mq_receive");

printf("Read %ld bytes; priority = %u\n", (long) numRead, prio);

if (write(STDOUT_FILENO, buffer, numRead) == -1)

errExit("write");

write(STDOUT_FILENO, "\n", 1);

exit(EXIT_SUCCESS);

}

pmsg/pmsg_receive.c

48.5.3. Отправка и получение сообщений с ограниченным временем ожидания

Функции mq_timedsend() и mq_timedreceive() являются прямыми аналогами mq_send() и mq_receive(), но с одним отличием: если операция не может быть выполнена немедленно и если среди атрибутов сообщения не указан флаг O_NONBLOCK, аргумент abs_timeout определяет продолжительность блокирования вызова.

#define _XOPEN_SOURCE 600

#include

#include

int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len,

unsigned int msg_prio, const struct timespec *abs_timeout);

Возвращает 0 при успешном завершении или -1 при ошибке

ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len,

unsigned int *msg_prio,

const struct timespec *abs_timeout);

Возвращает объем полученного сообщения (в байтах) или -1 при ошибке

Аргумент abs_timeout представляет собой структуру timespec (см. подраздел 23.4.2), которая задает время ожидания в виде количества секунд и наносекунд, прошедших с начала «эры UNIX». Для указания относительного времени ожидания можно воспользоваться функцией clock_gettime(), чтобы извлечь текущее значение часов CLOCK_REALTIME и затем добавить к нему необходимый период времени, получив тем самым структуру timespec, инициализированную должным образом.

Если вызов функции mq_timedsend() или mq_timedreceive() не завершается вовремя, то он возвращает ошибку ETIMEDOUT. Если в Linux аргументу abs_timeout присвоить значение NULL, то время ожидания будет неограниченным. Однако такая возможность не предусмотрена стандартом SUSv3, и портируемые приложения не могут на нее полагаться.

Функции mq_timedsend() и mq_timedreceive() изначально появились в стандарте POSIX.1d (1999) и доступны не во всех реализациях UNIX.

48.6. Оповещение о сообщении

Особенность, которая отличает очереди сообщений POSIX от их аналогов из System V, состоит в возможности получать асинхронные оповещения о появлении в ранее пустой очереди нового сообщения (то есть очередь перестает быть пустой). Это значит, что вместо выполнения блокирующего вызова mq_receive() или маркировки дескриптора очереди сообщений как неблокирующего с последующими регулярными «опросами» очереди процесс может подписаться на оповещения о приходе сообщений и заняться чем-нибудь другим. Оповещение можно получать либо в виде сигнала, либо путем вызова функции в отдельном потоке.

Оповещения, предоставляемые очередями сообщений POSIX, похожи на механизм оповещений для POSIX-таймеров, описанный в разделе 23.6 (оба этих программных интерфейса изначально появились в стандарте POSIX.1b).

Перейти на страницу:

Похожие книги