linux進程間通信之Posix消息隊列
Posix消息隊列與System V 消息隊列的用法很相似,主要有以下區別:
1. 對Posix消息隊列的讀取總是返回最高優先級的最早消息,對System V 消息隊列的讀取可以返回指定優先級的消息。
2. Posix 消息隊列允許產生一個信號或啟動一個線程去向一個空隊列寫入一個消息,System V消息隊列不可以。
Posix消息隊列常用函數及頭文件
#include <mqueue.h>
1. mqd_t mq_open(const char *name,int oflag,.../* mode_t mode, struct mq_attr *attr */);
返回值: 若成功則返回消息隊列描述符,若出錯返回-1
name: 為路徑
oflag: 為O_RDONLY , o_WRONLY或O_RDWR之一,也可按位或上O_CREAT,O_EXCL,O_NONBLOCK.
當用O_CREAT表示去創建一個新消息隊列且新消息隊列不存在時,參數mode 和 attr 就需要了。
mode: 所屬的用戶權限
attr:用於給新隊列指定某些屬性,如果為空指針,即為默認屬性。
mq_open 的返回值用於其他Posix消息隊列函數的第一個參數
2. int mq_close(mqd_t mqdes);
返回值:成功返回0,出錯返回-1
此函數功能是關閉該進程的該描述符指向的消息對列,但並不從系統中刪除。
3. int mq_unlink(const char *name);
返回值:成功返回0,出錯返回-1
此函數功能是刪除系統中name指向的消息對列。
4. int mq_getattr(mqd_t mqdes, struct mq_attr *attr);
int mq_setattr(mqd_t mqdes, const struct mq_attr *attr,struct mq_attr *oattr);
返回值:成功返回0,出錯返回-1
mq_attr結構有以下屬性:
struct mq_attr{
long mq_flags: //消息隊列標誌: 0,O_NONBLOCK
long mq_maxmsg; //消息隊列中允許的最多消息條數
long mq_msgsize; //每條消息中的最大字節數
long mq_curmsgs; //消息隊列中當前的消息數
};
mq_attr結構的指針可以作為mq_open的第四個參數傳遞(mq_attr *attr), 從而使當創建新的Posix消息隊列時可以指定mq_maxmsg和mq_msgsize屬性,其他兩個成語屬性被mq_open忽略。
mq_getattr: 獲取消息隊列當前屬性並填入attr指向的結構。
mq_setattr: 設置指定消息隊列的屬性,但是只使用mq_flags成員,以設置或清除費阻塞標誌。其他三個成員屬性被忽略(mq_maxmsg和mq_msgsize只能創建時指定,mq_curmsgs只能獲取不能設 置)。
5. int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio); 返回值:成功返回0,出錯返回-1
ssize_t mq_recieve(mqd_t mqdes, char *ptr, size_t len, unsigned int *priop);
返回值:成功則返回消息中字節數,出錯返回-1
mq_receive中的len參數的值不能小於mq_attr結構的mq_msgsize,否則,mq_receive立即返回EMSGSIZE錯誤。
mq_send中的prio參數是寫入消息的優先級,必須小於MQ_PRIO_MAX。 如果mq_receive的priop是一個非空指針,則會存放返回消息的優先級。如果不使用優先級,可以mq_send時指定優先級為0, mq_receive時指定最後一個參數為空指針。
代碼舉例:
創建Posix消息對列mq_creat.c
- #include "stdio.h"
- #include "stdlib.h"
- #include "mqueue.h"
- int main(char argc,char **argv)
- {
- mqd_t mqdc;
- if(argc>1)
- {
- mqdc=mq_open(argv[1],O_CREAT|O_RDWR|O_WRONLY,0666,NULL);
- if(mqdc==-1)
- printf("open error\n");
- mq_close(mqdc);
- }
- return 0;
- }
Posix消息對列發送代碼mq_send.c
- #include "stdlib.h"
- #include "stdio.h"
- #include "mqueue.h"
- int main(char argc,char **argv)
- {
- mqd_t mqds;
- void *ptr;
- size_t len;
- unsigned int prio;
- if(argc<3)
- printf("usage: ./send <name> <#bytes> <priority>\n");
- else
- {
- len=atoi(argv[2]);
- prio=atoi(argv[3]);
- mqds=mq_open(argv[1],O_WRONLY);
- if(mqds==-1)
- printf("open error\n");
- ptr=calloc(len,sizeof(char));
- mq_send(mqds,ptr,len,prio);
- mq_close(mqds);
- }
- return 0;
- }
Posix消息隊列接收代碼mq_receive.c
- #include "stdlib.h"
- #include "stdio.h"
- #include "mqueue.h"
- int main(char argc,char **argv)
- {
- mqd_t mqdr;
- ssize_t n;
- unsigned int prio;
- void *buff;
- struct mq_attr attr;
- if(argc>1)
- {
- mqdr=mq_open(argv[1],O_RDONLY);
- if(mqdr==-1)
- printf("open error\n");
- mq_getattr(mqdr,&attr);
- buff = malloc(attr.mq_msgsize);
- while((n=mq_receive(mqdr,buff,attr.mq_msgsize,&prio))<=0)
- {
- printf("wait\n");
- sleep(1);
- }
- printf("buff is %s,n=%d,prio=%d\n",buff,n,prio);
- mq_close(mqdr);
- }
- return 0;
- }
運行結果:
首先運行creat 創建新的消息隊列: $ ./creat /mq_test
然後運行send 發送消息:
$ ./send /mq_test 20 2
$ ./send /mq_test 80 8
$ ./send /mq_test 40 4
$ ./send /mq_test 60 6
最後運行receive接收消息:
$ ./receive /mq_test
buff is ,n=80,prio=8
$ ./receive /mq_test
buff is ,n=60,prio=6
$ ./receive /mq_test
buff is ,n=40,prio=4
$ ./receive /mq_test
buff is ,n=20,prio=2
從運行結果來看,發送消息程序依次發送了優先級為2,8,4,6長度為20,80,40,60四個消息; 然後運行接收程序後首先接收到的是優先級最高為8,長度為80的消息,按優先級由高到低依次接收。
因為發送的數據是calloc出來的隨機數據,打印結果無法顯示,只能顯示“buff is ”.
6. int mq_notify(mqd_t mqdes, const struct sigevent *notification); 返回值: 成功返回0,出錯返回-1 此函數為指定Posix消息隊列建立或刪除異步事件通知。 註意點: 1)任意時刻只能一個進程註冊接收某個消息隊列通知。 2)通知接收到後,已存在的註冊即被撤銷,如果需要再次接收,需要再次註冊。 3) 進程mq_receive的阻塞優先級大於註冊接收通知的優先級。 |
linux進程間通信之Posix消息隊列