Главная страница Взаимодействие нетривиальных процессов Листинг 5.6 (продолжение) 18 } 19 if (optind != argc - 1) 20 err quit( usage: mqreceive [ -n ] <nanie> ): 21 mqd = Mq open(argv[optind]. flags): 22 Mq getattr(mqd. &attr): 23 buff = Mailoc(attr.mq msgsize): 24 n = Mq receive(mqd. buff. attr.mq msgsize. &prio); 25 printfCread *ld bytes, priority = *u\n . (long) n. prio): 26 exit(O): 27 } Параметр -n запрещает блокировку 14-17 Параметр командной строки -п отключает блокировку. При этом программа возвращает сообщение об ошибке, если в очереди нет сообщений. Открытие очереди и получение атрибутов 21-25 Мы открываем очередь и получаем ее атрибуты, вызвав mq getattr. Нам обязательно нужно определить максимальный размер сообщения, потому что мы должны выделить буфер подходящего размера, чтобы вызвать mq recei ve. Программа выводит размер считываемого сообщения и его приоритет. ПРИМЕЧАНИЕ - Поскольку п имеет тип size t и мы не знаем, int это или long, мы преобразуем эту величину к типу long и используем строку формата %ld. В 64-разрядной реализации int будет 32-разрядным целым, а long и size t будут 64-разрядными целыми. Воспользуемся обеими программами, чтобы проиллюстрировать использование поля приоритета. Solaris % mqcreate /testl Solaris % mqgetattr /testl создаем очередь и смотрим на ее атрибуты max #msgs = 128. max #bytes/msg = 1024. Currently on queue = 0 Solaris % mqsend /testl 100 99999 отправка с некорректным значением приоритета mq send error: Invalid argument Solaris % mqsend /testl 100 6 100 байт, приоритет 6 Solaris % mqsend /testl 50 IB 50 байт, приоритет 18 Solaris % mqsend /testl 33 IB 33 байт, приоритет 18 Solaris % mqreceive /testl read 50 bytes, priority = 18 возвращается старейшее сообщение с Solaris % mqreceive /testl наивысшим приоритетом read 33 bytes, priority - 18 Solaris % mqreceive /testl read 100 bytes, priority - 6 Solaris % mqreceive -n /testl отключаем блокировку и убеждаемся, что очередь пуста mqreceive error: Resource temporarily unavailable Мы видим, что mq recei ve действительно возвращает старейшее сообщение с наивысшим приоритетом. 5.5. Ограничения очередей сообщений Мы уже сталкивались с двумя ограничениями, устанавливаемыми для любой очереди в момент ее создания: ш mq maxmsg - максимальное количество сообщений в очереди; Ш mq msgsize - максимальный размер сообщения. Не существует каких-либо ограничений на эти значения, хотя в рассматриваемых реализациях необходимо наличие в файловой системе места для файла требуемого размера. Кроме того, ограничения на эти величины могут накладываться реализацией виртуальной памяти (см. упражнение 5.5). Другие два ограничения определяются реализацией: Ш MQ OPEN MAX - максимальное количество очередей сообщений, которые могут быть одновременно открыты каким-либо процессом (Posix требует, чтобы эта величина была не меньше 8); i> MQ PRIO MAX - максимальное значение приоритета плюс один (Posix требует, чтобы эта величина была не меньше 32). Эти две константы часто определяются в заголовочном файле <uni std. h> и могут быть получены во время выполнения программы вызовом функции sysconf, как мы покажем далее. Пример: программа mqsysconf Программа в листинге 5.7 вызывает функцию sysconf и выводит два ограничения на очереди сообщений, определяемые реализацией. Листинг 5.7. Получение ограничений очередей с помощью sysconf pxmsg/mqsysconf.с 1 #include unpipc.h 2 int 3 mainCint argc. char **argv) 5 printfС MQ OPEN MAX = %й. MQ PRIO MAX = ld\n . 6 SysconfC SC MQ OPEN MAX). SysconfC SC MQ PRIO MAX)): 7 exitCO): Запустив эту программу в наших двух операционных системах, получим: Solaris % mqsysconf MQ OPEN MAX = 32. MQ PRIO MAX = 32 alpha % mqsysconf MQ OPEN MAX - 64. MQ PRIO MAX - 256 5.6. Функция mq notify Один из недостатков очередей сообщений System V, как мы увидим в главе 6, заключается в невозможности зедомить процесс о том, что в очередь было помещено сообщение. Мы можем заблокировать процесс при вызове msgrcv, но тогда мы не сможем выполнять другие действия во время ожидания сообщения. Если мы укажем флаг отключения блокировки при вызове msgrcv (IPC NOWAIT), процесс не будет заблокирован, но нам придется регулярно вызывать эту функцию, чтобы получить сообщение, когда оно будет отправлено. Мы уже говорили, что такая процедура называется опросом и на нее тратится лишнее время. Нужно, чтобы система сама уведомляла процесс о том, что в пустую очередь было помещено новое сообщение. ПРИМЕЧАНИЕ - В этом и всех последующих разделах данной главы обсуждаются более сложные вопросы, которые могут быть пропущены при первом чтении. Очереди сообщений Posix допускают асинхронное уведомление о событии, когда сообщение помещается в очередь. Это уведомление может быть реализовано либо отправкой сигнала, либо созданием программного потока для выполнения указанной функции. Мы включаем режим уведомления с помощью функции mq noti fy: #include <mqueue.li> int mq notify(niqd t mqdes. const struct sigevent *notification): I* Возвращает 0 в случае успешного выполнения. -1 - в случае ошибки */ Эта функция включает и выключает асинхронное уведомление о событии для указанной очереди. Структура sigevent впервые появилась в стандарте Posix.l для сигналов реального времени, о которых более подробно рассказано в следующем разделе. Эта структура и все новые константы, относящиеся к сигналам, определены в заголовочном файле <signa1 .li>: union sigval { int sivaljnt: /* целое значение */ void *sival ptr: /* указатель */ struct sigevent { int sigev not1fy: /* SIGEV {NONE.SIGNAL.THREAD} */ Int sigev s1gno: /* номер сигнала, если SIGEV SIGNAL */ union sigval sigev value: /* передается обработчику сигнала или потоку */ /* Следующие два поля определены для SIGEV THREAD */ void (*sigev notify function) (union sigval): ptliread attr t *sigev noti fy attributes: Мы вскоре приведем несколько примеров различных вариантов использования уведомления, но о правилах, действующих для этой функции всегда, можно упомянуть уже сейчас. 1. Если аргумент notification ненулевой, процесс ожидает уведомления при поступлении нового сообщения в указанную очередь, пустую на момент его поступления. Мы говорим, что процесс регистрируется на уведомление для данной очереди. 2. Если аргумент notification представляет собой нулевой указатель и процесс уже зарегистрирован на уведомление для данной очереди, то уведомление для него отключается.
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |