Главная страница Взаимодействие нетривиальных процессов 3. Только один процесс может быть зарегистрирован на уведомление для любой данной очереди в любой момент. 4. При помещении сообщения в пустую очередь, для которой имеется зарегистрированный на уведомление процесс, оно будет отправлено только в том случае, если нет заблокированных в вызове mqrecei ve для этой очереди процессов. Таким образом, блокировка в вызове mq receive имеет приоритет перед любой регистрацией на уведомление. 5. При отправке уведомления зарегистрированному процессу регистрация снимается. Процесс должен зарегистрироваться снова (если в этом есть необходимость), вызвав mq noti fy еще раз. ПРИМЕЧАНИЕ - С сигналами в Unix всегда была связана одна проблема: действие сигнала сбрасывалось на установленное по умолчанию каждый раз при отправке сигнала (раздел 10.4 [21]). Обычно первой функцией, вызываемой обработчиком сигнала, была signal, переопределявшая обработчик. Это создавало небольшой временной промежуток между отправкой сигнала и переопределением обработчика, в который процесс мог быть завершен при повторном появлении того же сигнала. На первый взгляд может показаться, что та же проблема должна возникать и при использовании mq notify, поскольку процесс должен перерегистрироваться каждый раз после появления уведомления. Однако очереди сообщений отличаются по своим свойствам от сигналов, поскольку необходимость отправки уведомления не может возникнуть, пока очередь не будет пуста. Следовательно, необходимо аккуратно перерегистрироваться на получение уведомления до считывания пришедшего сообщения из очереди. Пример: простая программа с уведомлением Прежде чем углубляться в тонкости сигналов реального времени и потоков Posix, мы напишем простейшую программу, включающую отправку сигнала SIGUSR1 при помещении сообщения в пустую очередь. Эта программа приведена в листинге 5.8, и мы отметим, что она содержит ошибку, о которой мы вскоре поговорим подробно. Листинг 5.8. Отправка S1GUSR1 при помещении сообщения в пустую очередь (неправильная версия программы) pxmsg/mqnotifysigl.c 1 #lnclude unpipc.h 2 niqd t mqd: 3 void *buff: 4 struct mq attr attr: 5 struct sigevent sigev: 6 static void sig usrl(int): 7 int 8 mainCint argc. char **argv) 10 if (argc != 2) 11 err quit( usage: mqnotifysigl <name> ): продолжение Листинг 5.8 (продолжение) 12 /* открываем очередь, получаем атрибуты, выделяем буфер */ 13 mqd = Mq open(argv[l]. 0 RDONLY): 14 Mq getattr(mqd. &attr): 15 buff = Mailoc(attr.mq msgsize): 16 /* устанавливаем обработчик, включаем уведомление */ 17 - Signal(SIGUSRl. sig usrl): 18 sigev.sigev notify = SIGEV SIGNAL: 19 sigev.sigev signo = SIGUSRl: 20 Mq notify(mqd. Ssigev): 21 for ( : ; ) 22 pauseO: /* все делает обработчик */ 23 exit(O): 24 } 25 static void 26 sig usrl(int signo) 27 { 28 ssize t n: 29 Mq notify(mqd. Ssigev): /* сначала перерегистрируемся */ 30 n = Mq receive(mqd. buff. attr.mq msgsize. NULL): 31 printfC SIGUSRl received, read ld bytesXn . (long) n): 32 return: 33 } Объявление глобальных переменных 2-6 Мы объявляем несколько глобальных переменных, используемых совместно функцией main и нашим обработчиком сигнала (sigusrl). Открытие очереди, получение атрибутов, выделение буфера чтения 12-15 Мы открываем очередь сообщений, получаем ее атрибуты и выделяем буфер считывания соответствующего размера. Установка обработчика сигнала, включение уведомления 16-20 Сначала мы устанавливаем свой обработчик для сигнала SIGUSRl. Мы присваиваем полю sigev notify структуры sigevent значение SIGEV SIGNAL, что говорит системе о необходимости отправки сигнала, когда очередь из пустой становится непустой. Полю s i деv s i gno присваивается значение, соответствующее тому сигналу, который мы хотим получить. Затем вызывается функция mq noti fy. Бесконечный цикл Функция mai п после этого зацикливается, й процесс приостанавливается при вызове pause, возвращающей -1 при получении сигнала. Получение сигнала, считывание сообщения Обработчик сигнала вызывает mq noti fy для перерегистрации, считывает сообщение и выводит его длину. В этой программе мы игнорируем приоритет полученного сообщения. ПРИМЕЧАНИЕ - Оператор return в конце sig usrl не требуется, поскольку возвращаемое значение отсутствует, а конец текста функции неявно предусматривает возвращение в вызвавшую программу. Тем не менее автор всегда записывает return явно, чтобы указать, что возвращение из этой функции может происходит с особенностями. Например, может произойти преждевременный возврат (с ошибкой EINTR) в потоке, обрабатывающем сигнал. Запустим теперь эту программу в одном из окон Solaris % mqcreate /testl Solaris % mqnotifysigl /testl и затем выполним следующую команду в другом окне Solaris % mqsend /testl 50 16 Как и ожидалось, программа mqnotifysigl выведет сообщение: SIGUSR1 received. read 50 bytes. Мы можем проверить, что только один процесс может быть зарегистрирован на получение уведомления в любой момент, запустив копию программы в другом окне: Solaris % mqnotifysigl /testl mq notify error: Device busy Это сообщение соответствует коду ошибки EBUSY. Сигналы Posix: функции типа Async-Signal-Safe Недостаток программы из листинга 5.8 в том, что она вызывает niq noti fy, niq recei ve и printf из обработчика сигнала. Ни одну из этих функций вызывать оттуда не следует. Функции, которые могут быть вызваны из обработчика сигнала, относятся к группе, называемой, согласно Posix, async-signal-safe functions (функции, обеспечивающие безопасную обработку асинхронных сигналов). В табл. 5.1 приведены эти функции по стандарту Posix вместе с некоторыми дополнительными, появившимися только в Unix 98. Функции, которых нет в этом списке, не должны вызываться из обработчика сигнала. Обратите внимание, что в списке отсутствуют стандартные функции библиотеки ввода-вывода и функции pthread XXX для работы с потоками. Из всех функций IPC, рассматриваемых в этой книге, в список попали только sem post, read и write (подразумевается, что последние две используются с программными каналами и FIFO). ПРИМЕЧАНИЕ - Стандарт ANSI С указывает четыре функции, которые могут быть вызваны из обработчика сигналов: abort, exit, longjmp, signal. Первые три отсутствуют в списке функций async-signal-safe стандарта Unix 98. Таблица 5.1. Функции, относящиеся к группе async-signal-safe access fpathconf rename sysconf aio return fstat rmdir tcdrain aio suspend fsync sem post tcflow -продолжен!
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |