Книга: UNIX: взаимодействие процессов
Пример: простая программа с уведомлением
Разделы на этой странице:
- Листинг 5.8. Отправка sigusr1 при помещении сообщения в пустую очередь (неправильная версия программы)
- Объявление глобальных переменных
- Открытие очереди, получение атрибутов, выделение буфера чтения
- Установка обработчика сигнала, включение уведомления
- Бесконечный цикл
- Получение сигнала, считывание сообщения
Пример: простая программа с уведомлением
Прежде чем углубляться в тонкости сигналов реального времени и потоков Posix, мы напишем простейшую программу, включающую отправку сигнала SI6USR1 при помещении сообщения в пустую очередь. Эта программа приведена в листинге 5.8, и мы отметим, что она содержит ошибку, о которой мы вскоре поговорим подробно.
Листинг 5.8. Отправка sigusr1 при помещении сообщения в пустую очередь (неправильная версия программы)
//pxmsg/mqnotifysigl.c
1 #include "unpipc.h"
2 mqd_t mqd;
3 void *buff;
4 struct mq_attr attr;
5 struct sigevent sigev;
6 static void sig_usrl(int);
7 int
8 main(int argc, char **argv)
9 {
10 if (argc != 2)
11 err_quit("usage: mqnotifysig1 <name>");
12 /* открываем очередь, получаем атрибуты, выделяем буфер */
13 mqd = Mq_open(argv[1], O_RDONLY);
14 Mq_getattr(mqd, &attr);
15 buff = Malloc(attr.mq_msgsize);
16 /* устанавливаем обработчик, включаем уведомление */
17 Signal(SIGUSR1, sig_usr1);
18 sigev.sigev_notify = SIGEV_SIGNAL;
19 sigev.sigev_signo = SIGUSR1;
20 Mq_notify(mqd, &sigev);
21 for (;;)
22 pause(); /* все делает обработчик */
23 exit(0);
24 }
25 static void
26 sig_usr1(int signo)
27 {
28 ssize_t n;
29 Mq_notify(mqd, &sigev); /* сначала перерегистрируемся */
30 n = Mq_receive(mqd, buff, attr.mq_msgsize, NULL);
31 printf("SIGUSR1 received, read %ld bytesn", (long) n);
32 return;
33 }
Объявление глобальных переменных
2-6 Мы объявляем несколько глобальных переменных, используемых совместно функцией main и нашим обработчиком сигнала (sig_usr1).
Открытие очереди, получение атрибутов, выделение буфера чтения
12-15 Мы открываем очередь сообщений, получаем ее атрибуты и выделяем буфер считывания соответствующего размера.
Установка обработчика сигнала, включение уведомления
16-20 Сначала мы устанавливаем свой обработчик для сигнала SIGUSR1. Мы присваиваем полю sigev_notify структуры sigevent значение SIGEV_SIGNAL, что говорит системе о необходимости отправки сигнала, когда очередь из пустой становится непустой. Полю sigev_signo присваивается значение, соответствующее тому сигналу, который мы хотим получить. Затем вызывается функция mq_notify.
Бесконечный цикл
Функция main после этого зацикливается, и процесс приостанавливается при вызове pause, возвращающей –1 при получении сигнала.
Получение сигнала, считывание сообщения
Обработчик сигнала вызывает mq_notify для перерегистрации, считывает сообщение и выводит его длину. В этой программе мы игнорируем приоритет полученного сообщения.
ПРИМЕЧАНИЕ
Оператор return в конце sig_usr1 не требуется, поскольку возвращаемое значение отсутствует, а конец текста функции неявно предусматривает возвращение в вызвавшую программу. Тем не менее автор всегда записывает return явно, чтобы указать, что возвращение из этой функции может происходит с особенностями. Например, может произойти преждевременный возврат (с ошибкой EINTR) в потоке, обрабатывающем сигнал.
Запустим теперь эту программу в одном из окон
solaris % mqcreate /test1
solaris % mqnotifysig1 /test1
и затем выполним следующую команду в другом окне
solaris % mqsend /test1 50 16
Как и ожидалось, программа mqnotifysig1 выведет сообщение: SIGUSR1 received, read 50 bytes.
Мы можем проверить, что только один процесс может быть зарегистрирован на получение уведомления в любой момент, запустив копию пpoгрaммы в другом окне:
solaris % mqnotifysig1 /test1
mq_notify error: Device busy
Это сообщение соответствует коду ошибки EBUSY.
- Пример: простая программа с уведомлением
- Сигналы Posix: функции типа Async-Signal-Safe
- Пример: уведомление сигналом
- Пример: уведомление сигналом с отключением блокировки
- Пример: уведомление с использованием sigwait вместо обработчика
- Пример: очереди сообщений Posix и функция select
- Пример: запуск нового потока
- Пример установочного скрипта
- Пример из практики
- ПРИМЕР ПРОСТОЙ ПРОГРАММЫ НА ЯЗЫКЕ СИ
- Примеры получения статистики
- Пример применения метода «пять почему»
- Пример 12-8. Частота встречаемости отдельных слов
- 1.2.5. Пример программы
- Пример 17-10. Блочный комментарий
- Примеры
- 2. Пример создания базового отношения в записи на псевдокоде
- Программа «Тайный покупатель»
- Пример 9-8. Содержимое $* и $@, когда переменная $IFS -- пуста