mq_notify()函數爲指定隊列創建或刪除異步事件通知,創建通知即某空消息隊列中若有新的消息,會發送一個信號或建立一個線程來執行指定的函數。shell
#include <mqueue.h> int 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 <stdio.h> #include <stdlib.h> #include <mqueue.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <signal.h> 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 <name>\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函數使用規則:
一、若是mq_notify()的notification參數非空,則代表將當前進程註冊爲接收某隊列的通知;
二、若是mq_notify()的notification參數爲空,則代表以前已存在的註冊將被撤消;
三、一個消息隊列任意時刻只能由一個進程註冊;
四、若有其餘進程mq_receive阻塞在該消息隊列時,信號不會發出,即mq_receive調用優先級更高;
五、通知被髮送給註冊進程時,註冊即被撤消,須從新註冊。異步
注:上面程序實際上是有問題,本處只作mq_notify函數的使用示例。函數
2011-11-18 任洪彩 qdurenhongcai@163.com線程
轉載請註明出處。指針