名字mq_notify - 注册一个当消息到达时的通知概要#include <mqueue.h> 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 域用于指明通知的方式。这个域可以有如下几个值:
对于一个消息队列只能有一个进程可以注册到达通知。 如果 sevp 是 NULL,并且调用进程当前已经在相应的队列里注册过通知,则这个注册被删除;此后其它进程就可以注册到这个队列里以接收通知。 消息通知只有在一个新消息到达且之前队列是空的情况下被递送。如果 mq_notify() 调用时队列非空,则通知会在队列变空之后且有新消息到达时递送。 如果其它进程或线程正在通过 mq_receive(3) 等待一个空队列的消息到达,则任何新到达的消息都被忽略:这些消息会传递给调用 mq_receive(3) 进程或线程,而消息通知注册仍然有效。 通知只发生一次:在一个通知递送之后,这个通知注册会被删除,并且其它进程可以注册一个通知。如果收到消息的进程想接收下一个通知,它可能使用 mq_notify() 请求一个全新通知。这可以在所有未读消息被收到完之前来执行。(此时把队列设置非阻塞模式会很有用,在清空队列消息的时候而不用担心一旦队列变空之后被阻塞。) 返回值成功时,mq_notify() 返回 0;错误时,返回 -1,并把 errno 设置为合适的值。错误
POSIX.1-2008 说当 sevp 是 NULL 时,实现可以产生一个 EINVAL 错误,并且调用进程不会被注册到队列 mqdes 的通知里。 遵循于POSIX.1-2001.示例这个程序注册一个通知到名为它命令行参数的消息队列里去。通知通过创建一个新的线程来执行。线程执行的函数从队列读取消息并终止进程。#include <pthread.h> #include <mqueue.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 %ld bytes from MQ\n", (long) nr); free(buf); exit(EXIT_SUCCESS); /* 终止进程 */ } int main(int argc, char *argv[]) { mqd_t mqdes; struct sigevent sev; if (argc != 2) { fprintf(stderr, "Usage: %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(); /* 进程将线上于线程函数 */ } |
|
来自: 杰出天下 > 《linux系统编程》