诺亚朵勒阿:mq_notify - man

来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 20:08:54

名字

mq_notify - 注册一个当消息到达时的通知

概要

#include int mq_notify(mqd_t mqdes, const struct sigevent *sevp);

需要 -lrt 来链接。

描述

mq_notify() 允许调用进程针对 mqdes 引用的空队列注册或注销新消息异步通知的递送。

sevp 参数是一个指向 sigevent 结构的指针。关于这个结构的定义与相关细节,见 sigevent(7)。

如果 sevp 是一个非空指针,那么 mq_notify() 注册调用进程以在消息到达时收到通知。sevp 指向的 sigevent 结构中的 sigev_notify 域用于指明通知的方式。这个域可以有如下几个值:

SIGEV_NONE
一个“空”通知:调用进程作为通知的目标被注册,但是当消息达到时,没有通知被递送。
SIGEV_SIGNAL
通过发送在 sigev_signo 指定的信号来通知进程。见 sigevent(7) 中的细节描述。siginfo_t 结构中的 si_code 域将被设置为 SI_MESGQ。进一步说,si_pid 将被设置为发送消息的进程的进程 ID,同时 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_notifySIGEV_SIGNALsevp->sigev_signo 不是一个信号值。
ENOMEM
内存不足。

POSIX.1-2008 说当 sevp 是 NULL 时,实现可以产生一个 EINVAL 错误,并且调用进程不会被注册到队列 mqdes 的通知里。

遵循于

POSIX.1-2001.

示例

这个程序注册一个通知到名为它命令行参数的消息队列里去。通知通过创建一个新的线程来执行。线程执行的函数从队列读取消息并终止进程。
#include #include #include #include #include #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 %ld bytes from MQ\n", (long) nr);free(buf);exit(EXIT_SUCCESS); /* 终止进程 */}intmain(int argc, char *argv[]){mqd_t mqdes;struct sigevent sev;if (argc != 2) {fprintf(stderr, "Usage: %s \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(); /* 进程将线上于线程函数 */}