mq_notify - включает
уведомление
при
поступлении
сообщения
Real-time library (
librt,
-lrt)
#include <mqueue.h>
#include <signal.h> /* Definition of SIGEV_* constants */
int mq_notify(mqd_t mqdes, const struct sigevent *sevp);
Функция
mq_notify()
позволяет
вызывающему
процессу
регистрироваться
или
отменять
регистрацию
доставки
анонимных
уведомлений
при
появлении
нового
сообщения
в пустой
очереди
сообщений,
на которую
ссылается
дескриптор
очереди
сообщений
mqdes.
Аргумент
sevp
является
указателем
на
структуру
sigevent.
Определение
и описание
структуры
смотрите в
sigevent(7).
Если
sevp не
равен null, то
mq_notify()
регистрирует
вызывающий
процесс
для
получения
уведомлений
о
сообщениях.
В поле
sigev_notify
структуры
sigevent, на
которую
указывает
sevp, задаётся
способ
выполнения
уведомления.
Это поле
может
содержать
одно из
следующих
значений:
- SIGEV_NONE
- «Нулевое»
уведомление:
хотя
вызывающий
процесс и
регистрируется
как
уведомляемый,
при
появлении
сообщения
уведомление
не будет
отправлено.
- SIGEV_SIGNAL
- Уведомлять
процесс
посредством
отправки
сигнала,
указанного
в sigev_signo.
Подробности
смотрите в
sigevent(7). Поле si_code
структуры
siginfo_t будет
изменено
на SI_MESGQ.
Также,
значение
si_pid будет
изменено
на PID
процесса,
который
посылается
сообщение,
а значение
si_uid будет
изменено
на
реальный
пользовательский
ID
посылающего
процесса.
- SIGEV_THREAD
- При
доставке
сообщения
вызвать
sigev_notify_function, как
если бы это
была
начальная
функция
новой нити.
Подробности
смотрите в
sigevent(7).
Только
один
процесс
может быть
зарегистрирован,
чтобы
получить
уведомление
из очереди
сообщений.
Если
sevp
равно NULL и
вызывающий
процесс
уже
зарегистрирован
принимать
сообщения
для этой
очереди
сообщений,
то
регистрация
удаляется;
после
этого
другой
процесс
может
зарегистрироваться
для
получения
уведомлений
о
сообщениях
в этой
очереди.
Уведомление
о
сообщение
возникает
только при
поступлении
нового
сообщения
и если
очередь до
этого была
пуста. Если
очередь не
пуста на
момент
вызова
mq_notify(),
то
уведомление
будет
происходить
только
после
опустошения
очереди и
поступлении
нового
сообщения.
Если
другой
процесс
или нить
ожидают
чтения
сообщения
из пустой
очереди с
помощью
mq_receive(3),
то все
регистрации
по
уведомлению
игнорируются;
сообщение
доставляется
процесс
или нити
вызвавшей
mq_receive(3), и
регистрация
уведомления
о
сообщении
остаётся
как была.
Уведомление
выполняется
один раз:
после
доставки
уведомления
регистрация
удаляется
и другой
процесс
может
зарегистрироваться
для
уведомления.
Если
уведомлённый
процесс
хочет
получить
следующее
уведомление,
то он может
использовать
mq_notify() для
запроса
уведомления
в
дальнейшем.
Это должно
быть
сделано до
исчезновения
всех
непрочитанных
сообщений
из очереди
(переключение
очереди в
неблокирующий
режим
полезно
для
опустошения
очереди
сообщений
без
блокировки,
если
очередь
пуста).
При
успешном
выполнении
mq_notify()
возвращает
0; при ошибке
возвращает
-1, а в
errno
помещается
код ошибки.
- EBADF
- В mqdes
размещён
некорректный
дескриптор
очереди
сообщений.
- EBUSY
- Другой
процесс
уже
зарегистрировался,
чтобы
получать
уведомление
из этой
очереди
сообщений.
- EINVAL
- Значение
sevp->sigev_notify
содержит
недопустимое
значение;
или sevp->sigev_notify
равно SIGEV_SIGNAL и
sevp->sigev_signo не
содержит
корректного
номера
сигнала.
- ENOMEM
- Недостаточно
памяти.
В POSIX.1-2008 сказано,
что
реализация
может
генерировать
ошибку
EINVAL,
если
sevp
равно NULL, и
вызывающий
ещё не
зарегистрирован
для
получения
уведомлений
из очереди
mqdes.
Описание
терминов
данного
раздела
смотрите в
attributes(7).
Интерфейс |
Атрибут |
Значение |
mq_notify() |
Безвредность
в нитях |
MT-Safe |
POSIX.1-2001.
В glibc
библиотечная
функция
mq_notify()
реализована
на основе
системного
вызова с
тем же
именем.
Если
sevp
равно NULL или
задаёт
механизм
уведомления
не
SIGEV_THREAD, то
библиотечная
функция
напрямую
вызывает
системный
вызов.
Большая
часть
реализации
SIGEV_THREAD
располагается
внутри
библиотеки,
а не в ядре
(эта
необходимость
возникает
из-за того,
что нить,
вовлечённая
в
обработку
уведомления,
должна
управляться
в
библиотечной
реализации
C нитей POSIX). В
реализации
задействуется
неструктурированный
сокет
netlink(7) и
создаётся
новая нить
для
каждого
уведомления,
доставляемого
процессу.
В
следующей
программе
показана
регистрация
запроса
уведомления
для
очереди
сообщений
с именем,
указанном
в
аргументе
командной
строки.
Уведомление
выполняется
создаваемой
нитью. Нить
выполняет
функцию,
которая
читает
одно
сообщение
из очереди
и
завершает
процесс.
#include <mqueue.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static void /* начальная функция нити */
tfunc(union sigval sv)
{
struct mq_attr attr;
ssize_t nr;
void *buf;
mqd_t mqdes = *((mqd_t *) sv.sival_ptr);
/* Определяем максимальный размер сообщения; выделяем буфер для принимаемого сообщения */
if (mq_getattr(mqdes, &attr) == -1)
handle_error("mq_getattr");
buf = malloc(attr.mq_msgsize);
if (buf == NULL)
handle_error("malloc");
nr = mq_receive(mqdes, buf, attr.mq_msgsize, NULL);
if (nr == -1)
handle_error("mq_receive");
printf("Read %zd bytes from MQ\n", nr);
free(buf);
exit(EXIT_SUCCESS); /* Завершение процесса */
}
int
main(int argc, char *argv[])
{
mqd_t mqdes;
struct sigevent sev;
if (argc != 2) {
fprintf(stderr, "Использование: %s <mq-name>\n", argv[0]);
exit(EXIT_FAILURE);
}
mqdes = mq_open(argv[1], O_RDONLY);
if (mqdes == (mqd_t) -1)
handle_error("mq_open");
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = tfunc;
sev.sigev_notify_attributes = NULL;
sev.sigev_value.sival_ptr = &mqdes; /* аргументы функции нити */
if (mq_notify(mqdes, &sev) == -1)
handle_error("mq_notify");
pause(); /* процесс будет завершён из функции нити */
}
mq_close(3),
mq_getattr(3),
mq_open(3),
mq_receive(3),
mq_send(3),
mq_unlink(3),
mq_overview(7),
sigevent(7)
Русский
перевод
этой
страницы
руководства
был сделан
aereiae <
[email protected]>, Alexey <
[email protected]>, Azamat
Hackimov <
[email protected]>, Dmitriy S. Seregin
<
[email protected]>, Dmitry Bolkhovskikh <
[email protected]>,
ITriskTI <
[email protected]>, Max Is <
[email protected]>, Yuri
Kozlov <
[email protected]>, Иван
Павлов <
[email protected]>
и Малянов
Евгений
Викторович
<
[email protected]>
Этот
перевод
является
бесплатной
документацией;
прочитайте
Стандартную
общественную
лицензию GNU
версии 3
или более
позднюю,
чтобы
узнать об
условиях
авторского
права. Мы не
несем
НИКАКОЙ
ОТВЕТСТВЕННОСТИ.
Если вы
обнаружите
ошибки в
переводе
этой
страницы
руководства,
пожалуйста,
отправьте
электронное
письмо на
[email protected]