■ MQ_OPEN_MAX — максимальное количество очередей сообщений, которые могут быть одновременно открыты каким-либо процессом (Posix требует, чтобы эта величина была не меньше 8);

■ MQ_PRIO_MAX — максимальное значение приоритета плюс один (Posix требует, чтобы эта величина была не меньше 32).

Эти две константы часто определяются в заголовочном файле unistd.h и могут быть получены во время выполнения программы вызовом функции sysconf, как мы покажем далее.

<p>Пример: программа mqsysconf</p>

Программа в листинге 5.7 вызывает функцию sysconf и выводит два ограничения на очереди сообщений, определяемые реализацией.

Листинг 5.7. Получение ограничений очередей с помощью sysconf

//pxmsg/mqsysconf.с

1 #include "unpipc.h"

2 int

3 main(int argc, char **argv)

4 {

5  printf("MQ_OPEN_MAX = %ld, MQ_PRIO_MAX = %ld\n",

6  Sysconf(_SC_MQ_OPEN_MAX), Sysconf(_SC_MQ_PRIO_MAX));

7  exit(0);

8 }

Запустив эту программу в наших двух операционных системах, получим:

solaris % mqsysconf

MQ_OPEN_MAX = 32, MQ_PRIO_MAX = 32

alpha % mqsysconf

MQ_OPEN_MAX = 64, MQ_PRIO_MAX = 256

<p>5.6. Функция mq_notify</p>

Один из недостатков очередей сообщений System V, как мы увидим в главе 6, заключается в невозможности уведомить процесс о том, что в очередь было помещено сообщение. Мы можем заблокировать процесс при вызове msgrcv, но тогда мы не сможем выполнять другие действия во время ожидания сообщения. Если мы укажем флаг отключения блокировки при вызове msgrcv (IPC_NOWAIT), процесс не будет заблокирован, но нам придется регулярно вызывать эту функцию, чтобы получить сообщение, когда оно будет отправлено. Мы уже говорили, что такая процедура называется опросом и на нее тратится лишнее время. Нужно, чтобы система сама уведомляла процесс о том, что в пустую очередь было помещено новое сообщение.

ПРИМЕЧАНИЕ

В этом и всех последующих разделах данной главы обсуждаются более сложные вопросы, которые могут быть пропущены при первом чтении. 

Очереди сообщений Posix допускают асинхронное уведомление о событии, когда сообщение помещается в очередь. Это уведомление может быть реализовано либо отправкой сигнала, либо созданием программного потока для выполнения указанной функции.

Мы включаем режим уведомления с помощью функции mq_notify:

#include mqueue.h

int mq_notify(mqd_t mqdes, const struct sigevent *notification);

/* Возвращает 0 в случае успешного выполнения, –1 – в случае ошибки */

Эта функция включает и выключает асинхронное уведомление о событии для указанной очереди. Структура sigevent впервые появилась в стандарте Posix.1 для сигналов реального времени, о которых более подробно рассказано в следующем разделе. Эта структура и все новые константы, относящиеся к сигналам, определены в заголовочном файле signal.h:

union sigval {

 int sival_int; /* целое значение */

 void *sival_ptr; /* указатель */

};

struct sigevent {

 int sigev_notify; /* SIGEV_{NONE,SIGNAL,THREAD} */

 int sigev_signo; /* номер сигнала, если SIGEV_SIGNAL */

 union sigval sigev_value; /* передается обработчику сигнала или потоку */

/* Следующие два поля определены для SIGEV_THREAD */

void (*sigev_notify_function) (union sigval);

pthread_attr_t *sigev_notify_attributes;

Мы вскоре приведем несколько примеров различных вариантов использования уведомления, но о правилах, действующих для этой функции всегда, можно упомянуть уже сейчас.

1. Если аргумент notification ненулевой, процесс ожидает уведомления при поступлении нового сообщения в указанную очередь, пустую на момент его поступления. Мы говорим, что процесс регистрируется на уведомление для данной очереди.

2. Если аргумент notification представляет собой нулевой указатель и процесс уже зарегистрирован на уведомление для данной очереди, то уведомление для него отключается.

3. Только один процесс может быть зарегистрирован на уведомление для любой данной очереди в любой момент.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже