對消息隊列的操作無非有以下三種類型:
1、 打開或創建消息隊列
消息隊列的內核持續性要求每一個消息隊列都在系統范圍內相應唯一的鍵值,所以,要獲得一個消息隊列的描寫敘述字,僅僅需提供該消息隊列的鍵值就可以;
注:消息隊列描寫敘述字是由在系統范圍內唯一的鍵值生成的,而鍵值能夠看作相應系統內的一條路經。
2、 讀寫操作
消息讀寫操作很easy,對開發者來說,每一個消息都相似例如以下的 數據 結構:
|
mtype成員代表消息類型,從消息隊列中讀取消息的一個重要根據就是消息的類型;mtext是消息內容,當然長度不一定為1。因此,對于發送消息來說,首先預置一個msgbuf緩沖區并寫入消息類型和內容,調用對應的發送函數就可以;對讀取消息來說,首先分配這樣一個msgbuf緩沖區,然后把消息讀入該緩沖區就可以。
3、 獲得或設置消息隊列屬性:
消息隊列的信息基本上都保存在消息隊列頭中,因此,能夠分配一個相似于消息隊列頭的結構(struct msqid_ds,見 附錄 2 ),來返回消息隊列的屬性;相同能夠設置該 數據 結構。
消息隊列API
1、文件名稱到鍵值
|
它返回與路徑pathname相相應的一個鍵值。該函數不直接對消息隊列操作,但在調用ipc(MSGGET,…)或msgget()來獲得消息隊列描寫敘述字前,往往要調用該函數。典型的調用代碼是:
|
2.系統V消息隊列API
系統V消息隊列API共同擁有四個,使用時須要包含幾個頭文件:
|
1)int msgget(key_t key, int msgflg)
參數key是一個鍵值,由ftok獲得;msgflg參數是一些標志位。該調用返回與健值key相相應的消息隊列描寫敘述字。
在下面兩種情況下,該調用將創建一個新的消息隊列:
- 假設沒有消息隊列與健值key相相應,而且msgflg中包括了IPC_CREAT標志位;
- key參數為IPC_PRIVATE;
參數msgflg能夠為下面:IPC_CREAT、IPC_EXCL、IPC_NOWAIT或三者的或結果。
調用返回: 成功返回消息隊列描寫敘述字,否則返回-1。
注:參數key設置成常數IPC_PRIVATE并不意味著其它進程不能訪問該消息隊列,僅僅意味著即將創建新的消息隊列。
2)int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg);
該系統調用從msgid代表的消息隊列中讀取一個消息,并把消息存儲在msgp指向的msgbuf結構中。
msqid為消息隊列描寫敘述字;消息返回后存儲在msgp指向的地址,msgsz指定msgbuf的mtext成員的長度(即消息內容的長度),msgtyp為請求讀取的消息類型;讀消息標志msgflg能夠為下面幾個常值的或:
- IPC_NOWAIT 假設沒有滿足條件的消息,調用馬上返回,此時,errno=ENOMSG
- IPC_EXCEPT 與msgtyp>0配合使用,返回隊列中第一個類型不為msgtyp的消息
- IPC_NOERROR 假設隊列中滿足條件的消息內容大于所請求的msgsz字節,則把該消息截斷,截斷部分將丟失。
msgrcv手冊中具體給出了消息類型取不同值時(>0; <0; =0),調用將返回消息隊列中的哪個消息。
msgrcv()解除堵塞的條件有三個:
- 消息隊列中有了滿足條件的消息;
- msqid代表的消息隊列被刪除;
- 調用msgrcv()的進程被信號中斷;
調用返回: 成功返回讀出消息的實際字節數,否則返回-1。
3)int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg);
向msgid代表的消息隊列發送一個消息,即將發送的消息存儲在msgp指向的msgbuf結構中,消息的大小由msgze指定。
對發送消息來說,有意義的msgflg標志為IPC_NOWAIT,指明在消息隊列沒有足夠空間容納要發送的消息時,msgsnd是否等待。造成msgsnd()等待的條件有兩種:
- 當前消息的大小與當前消息隊列中的字節數之和超過了消息隊列的總容量;
- 當前消息隊列的消息數(單位"個")不小于消息隊列的總容量(單位"字節數"),此時,盡管消息隊列中的消息數目非常多,但基本上都僅僅有一個字節。
msgsnd()解除堵塞的條件有三個:
- 不滿足上述兩個條件,即消息隊列中有容納該消息的空間;
- msqid代表的消息隊列被刪除;
- 調用msgsnd()的進程被信號中斷;
調用返回: 成功返回0,否則返回-1。
4)int msgctl(int msqid, int cmd, struct msqid_ds *buf);
該系統調用對由msqid標識的消息隊列運行cmd操作,共同擁有三種cmd操作:IPC_STAT、IPC_SET 、IPC_RMID。
- IPC_STAT:該命令用來獲取消息隊列信息,返回的信息存貯在buf指向的msqid結構中;
- IPC_SET:該命令用來設置消息隊列的屬性,要設置的屬性存儲在buf指向的msqid結構中;可設置屬性包含:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,同一時候,也影響msg_ctime成員。
- IPC_RMID:刪除msqid標識的消息隊列;
調用返回: 成功返回0,否則返回-1。
----------------------------------------------------------------------------------------------------------------------
/*msgserver.c*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#define?? MSG_FILE "msgserver.c"
#define?? BUFFER 255
#define?? PERM S_IRUSR|S_IWUSR
/* 服務端創建的消息隊列最后沒有刪除,我們要使用ipcrm命令來刪除的 */
/* ipcrm -q <msqid> */
struct msgtype {
??? long mtype;
??? char buffer[BUFFER+1];
};
int main()
{
??? struct msgtype msg;
??? key_t key;
??? int msgid;
???
??? if((key=ftok(MSG_FILE,'a'))==-1)
??? {
??????? fprintf(stderr,"Creat Key Error:%s/n", strerror(errno));
??????? exit(1);
??? }
??? if((msgid=msgget(key, PERM|IPC_CREAT|IPC_EXCL))==-1)
??? {
??????? fprintf(stderr, "Creat Message Error:%s/n", strerror(errno));
??????? exit(1);
??? }
??? printf("msqid = %d/n", msgid);
??? while(1)
??? {
??????? msgrcv(msgid, &msg, sizeof(struct msgtype), 1, 0);
??????? fprintf(stderr,"Server Receive:%s/n", msg.buffer);
??????? msg.mtype = 2;
??????? msgsnd(msgid, &msg, sizeof(struct msgtype), 0);
??? }
??? exit(0);
}
/* msgclient.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#define?? MSG_FILE "msgserver.c"
#define?? BUFFER 255
#define?? PERM S_IRUSR|S_IWUSR
struct msgtype {
??? long mtype;
??? char buffer[BUFFER+1];
};
int main(int argc, char **argv)
{
??? struct msgtype msg;
??? key_t key;
??? int msgid;
???
??? if(argc != 2)
??? {
??????? fprintf(stderr,"Usage:%s string/n", argv[0]);
??????? exit(1);
??? }
???
??? if((key=ftok(MSG_FILE,'a'))==-1)
??? {
??????? fprintf(stderr,"Creat Key Error:%s/n", strerror(errno));
??????? exit(1);
??? }
???
??? if((msgid=msgget(key, PERM))==-1)
??? {
??????? fprintf(stderr,"Creat Message? Error:%s/n", strerror(errno));
??????? exit(1);
??? }
???
??? msg.mtype = 1;
??? strncpy(msg.buffer, argv[1], BUFFER);
??? msgsnd(msgid, &msg, sizeof(struct msgtype), 0);?
??? memset(&msg, '/0', sizeof(struct msgtype));
??? msgrcv(msgid, &msg, sizeof(struct msgtype), 2, 0);
??? fprintf(stderr, "Client receive:%s/n", msg.buffer);
??? exit(0);
}??
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
