mq_notify()函数为指定队列建立或删除异步事件通知,建立通知即某空消息队列中如有新的消息,会发送一个信号或创建一个线程来执行指定的函数。
#includeint mq_notify(mqd_t mqdes, const struct sigevent *notification);成功返回0,出错则为-1
给出struct sigevent定义:
union signal{ int sival_int; /*整数值*/ void *sival_ptr; /*指针值*/};struct sigevent{ int sigev_notify; /*通知类型:SIGEV_NONE、SIGEV_SIGNAL、SIGEV_THREAD*/ int sigev_signo; /*信号值*/ union sigval sigev_value; /*传递给信号处理函数或线程的信号值*/ void (*sigev_notify_function)(union sigval); /*线程处理函数*/ pthread_attr_t *sigev_notify_attributes; /*线程属性*/};
下面给出示例代码:
#include#include #include #include #include #include #include #include #include mqd_t mqd;struct mq_attr attr;struct sigevent sigev;char *ptr;unsigned int prio;size_t n;int rc;void sig_usr1(int signo);/*读取某消息队列,消息队列名通过参数传递*//*当有消息放置到某个空的队列中时产生SIGUSR1信号*/int main(int argc, char *argv[]){ if(argc != 2) { printf("Usage: mqnotifysig1 \n"); exit(1); } /*只读模式打开消息队列*/ mqd = mq_open(argv[1], O_RDONLY); if(mqd < 0) { perror("打开消息队列失败"); exit(1); } // 取得消息队列属性,根据mq_msgsize动态申请内存 rc = mq_getattr(mqd, &attr); if(rc < 0) { perror("取得消息队列属性失败"); exit(1); } /*动态申请保证能存放单条消息的内存*/ ptr = calloc(attr.mq_msgsize, sizeof(char)); if(NULL == ptr) { printf("动态申请内存失败\n"); mq_close(mqd); exit(1); } //注册信号函数 signal(SIGUSR1, sig_usr1); sigev.sigev_notify = SIGEV_SIGNAL; sigev.sigev_signo = SIGUSR1; //注册通知 rc = mq_notify(mqd, &sigev); // 读取前需要再次注册 if(rc < 0) { perror("通知注册失败"); mq_close(mqd); free(ptr); exit(1); } for(;;) { pause(); } return 0;}void sig_usr1(int signo){ rc = mq_notify(mqd, &sigev); // 读取前需要再次注册 if(rc < 0) { perror("通知注册失败"); mq_close(mqd); free(ptr); exit(1); } /*接收一条消息*/ n = mq_receive(mqd, ptr, attr.mq_msgsize, &prio); if(n < 0) { perror("读取失败"); mq_close(mqd); free(ptr); exit(1); } printf("读取 %ld 字节\n优先级为 %u\n", (long)n, prio);}
编译并执行:
[infor@s123 PosixMq]$ gcc -o mqnotifysig1 mqnotifysig1.c -lrt[infor@s123 PosixMq]$ ./mqnotifysig1 /tmp
此时消息队列内没有消息,程序进入睡眠,等待信号到来。再开启一个终端,通过另外的程序往消息队列写消息:
[infor@s123 PosixMq]$ ./sendmq /tmp 200 16[infor@s123 PosixMq]$ ./sendmq /tmp 100 17[infor@s123 PosixMq]$ ./sendmq /tmp 50 18
可以看到先前的程序:
[infor@s123 PosixMq]$ gcc -o mqnotifysig1 mqnotifysig1.c -lrt[infor@s123 PosixMq]$ ./mqnotifysig1 /tmp读取 200 字节优先级为 16读取 100 字节优先级为 17读取 50 字节优先级为 18
mq_notify函数使用规则:
1、如果mq_notify()的notification参数非空,则表明将当前进程注册为接收某队列的通知;
2、如果mq_notify()的notification参数为空,则表明之前已存在的注册将被撤消; 3、一个消息队列任意时刻只能由一个进程注册; 4、如有其他进程mq_receive阻塞在该消息队列时,信号不会发出,即mq_receive调用优先级更高; 5、通知被发送给注册进程时,注册即被撤消,须重新注册。注:上面程序其实是有问题,本处只做mq_notify函数的使用示例。
2011-11-18 任洪彩 qdurenhongcai@163.com
转载请注明出处。