對(duì)消息隊(duì)列的操作無(wú)非有以下三種類型:
1、 打開(kāi)或創(chuàng)建消息隊(duì)列
消息隊(duì)列的內(nèi)核持續(xù)性要求每一個(gè)消息隊(duì)列都在系統(tǒng)范圍內(nèi)相應(yīng)唯一的鍵值,所以,要獲得一個(gè)消息隊(duì)列的描寫(xiě)敘述字,僅僅需提供該消息隊(duì)列的鍵值就可以;
注:消息隊(duì)列描寫(xiě)敘述字是由在系統(tǒng)范圍內(nèi)唯一的鍵值生成的,而鍵值能夠看作相應(yīng)系統(tǒng)內(nèi)的一條路經(jīng)。
2、 讀寫(xiě)操作
消息讀寫(xiě)操作很easy,對(duì)開(kāi)發(fā)者來(lái)說(shuō),每一個(gè)消息都相似例如以下的 數(shù)據(jù) 結(jié)構(gòu):
|
mtype成員代表消息類型,從消息隊(duì)列中讀取消息的一個(gè)重要根據(jù)就是消息的類型;mtext是消息內(nèi)容,當(dāng)然長(zhǎng)度不一定為1。因此,對(duì)于發(fā)送消息來(lái)說(shuō),首先預(yù)置一個(gè)msgbuf緩沖區(qū)并寫(xiě)入消息類型和內(nèi)容,調(diào)用對(duì)應(yīng)的發(fā)送函數(shù)就可以;對(duì)讀取消息來(lái)說(shuō),首先分配這樣一個(gè)msgbuf緩沖區(qū),然后把消息讀入該緩沖區(qū)就可以。
3、 獲得或設(shè)置消息隊(duì)列屬性:
消息隊(duì)列的信息基本上都保存在消息隊(duì)列頭中,因此,能夠分配一個(gè)相似于消息隊(duì)列頭的結(jié)構(gòu)(struct msqid_ds,見(jiàn) 附錄 2 ),來(lái)返回消息隊(duì)列的屬性;相同能夠設(shè)置該 數(shù)據(jù) 結(jié)構(gòu)。
消息隊(duì)列API
1、文件名稱到鍵值
|
它返回與路徑pathname相相應(yīng)的一個(gè)鍵值。該函數(shù)不直接對(duì)消息隊(duì)列操作,但在調(diào)用ipc(MSGGET,…)或msgget()來(lái)獲得消息隊(duì)列描寫(xiě)敘述字前,往往要調(diào)用該函數(shù)。典型的調(diào)用代碼是:
|
2.系統(tǒng)V消息隊(duì)列API
系統(tǒng)V消息隊(duì)列API共同擁有四個(gè),使用時(shí)須要包含幾個(gè)頭文件:
|
1)int msgget(key_t key, int msgflg)
參數(shù)key是一個(gè)鍵值,由ftok獲得;msgflg參數(shù)是一些標(biāo)志位。該調(diào)用返回與健值key相相應(yīng)的消息隊(duì)列描寫(xiě)敘述字。
在下面兩種情況下,該調(diào)用將創(chuàng)建一個(gè)新的消息隊(duì)列:
- 假設(shè)沒(méi)有消息隊(duì)列與健值key相相應(yīng),而且msgflg中包括了IPC_CREAT標(biāo)志位;
- key參數(shù)為IPC_PRIVATE;
參數(shù)msgflg能夠?yàn)橄旅妫篒PC_CREAT、IPC_EXCL、IPC_NOWAIT或三者的或結(jié)果。
調(diào)用返回: 成功返回消息隊(duì)列描寫(xiě)敘述字,否則返回-1。
注:參數(shù)key設(shè)置成常數(shù)IPC_PRIVATE并不意味著其它進(jìn)程不能訪問(wèn)該消息隊(duì)列,僅僅意味著即將創(chuàng)建新的消息隊(duì)列。
2)int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg);
該系統(tǒng)調(diào)用從msgid代表的消息隊(duì)列中讀取一個(gè)消息,并把消息存儲(chǔ)在msgp指向的msgbuf結(jié)構(gòu)中。
msqid為消息隊(duì)列描寫(xiě)敘述字;消息返回后存儲(chǔ)在msgp指向的地址,msgsz指定msgbuf的mtext成員的長(zhǎng)度(即消息內(nèi)容的長(zhǎng)度),msgtyp為請(qǐng)求讀取的消息類型;讀消息標(biāo)志msgflg能夠?yàn)橄旅鎺讉€(gè)常值的或:
- IPC_NOWAIT 假設(shè)沒(méi)有滿足條件的消息,調(diào)用馬上返回,此時(shí),errno=ENOMSG
- IPC_EXCEPT 與msgtyp>0配合使用,返回隊(duì)列中第一個(gè)類型不為msgtyp的消息
- IPC_NOERROR 假設(shè)隊(duì)列中滿足條件的消息內(nèi)容大于所請(qǐng)求的msgsz字節(jié),則把該消息截?cái)啵財(cái)嗖糠謱G失。
msgrcv手冊(cè)中具體給出了消息類型取不同值時(shí)(>0; <0; =0),調(diào)用將返回消息隊(duì)列中的哪個(gè)消息。
msgrcv()解除堵塞的條件有三個(gè):
- 消息隊(duì)列中有了滿足條件的消息;
- msqid代表的消息隊(duì)列被刪除;
- 調(diào)用msgrcv()的進(jìn)程被信號(hào)中斷;
調(diào)用返回: 成功返回讀出消息的實(shí)際字節(jié)數(shù),否則返回-1。
3)int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg);
向msgid代表的消息隊(duì)列發(fā)送一個(gè)消息,即將發(fā)送的消息存儲(chǔ)在msgp指向的msgbuf結(jié)構(gòu)中,消息的大小由msgze指定。
對(duì)發(fā)送消息來(lái)說(shuō),有意義的msgflg標(biāo)志為IPC_NOWAIT,指明在消息隊(duì)列沒(méi)有足夠空間容納要發(fā)送的消息時(shí),msgsnd是否等待。造成msgsnd()等待的條件有兩種:
- 當(dāng)前消息的大小與當(dāng)前消息隊(duì)列中的字節(jié)數(shù)之和超過(guò)了消息隊(duì)列的總?cè)萘浚?
- 當(dāng)前消息隊(duì)列的消息數(shù)(單位"個(gè)")不小于消息隊(duì)列的總?cè)萘浚▎挝?字節(jié)數(shù)"),此時(shí),盡管消息隊(duì)列中的消息數(shù)目非常多,但基本上都僅僅有一個(gè)字節(jié)。
msgsnd()解除堵塞的條件有三個(gè):
- 不滿足上述兩個(gè)條件,即消息隊(duì)列中有容納該消息的空間;
- msqid代表的消息隊(duì)列被刪除;
- 調(diào)用msgsnd()的進(jìn)程被信號(hào)中斷;
調(diào)用返回: 成功返回0,否則返回-1。
4)int msgctl(int msqid, int cmd, struct msqid_ds *buf);
該系統(tǒng)調(diào)用對(duì)由msqid標(biāo)識(shí)的消息隊(duì)列運(yùn)行cmd操作,共同擁有三種cmd操作:IPC_STAT、IPC_SET 、IPC_RMID。
- IPC_STAT:該命令用來(lái)獲取消息隊(duì)列信息,返回的信息存貯在buf指向的msqid結(jié)構(gòu)中;
- IPC_SET:該命令用來(lái)設(shè)置消息隊(duì)列的屬性,要設(shè)置的屬性存儲(chǔ)在buf指向的msqid結(jié)構(gòu)中;可設(shè)置屬性包含:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes,同一時(shí)候,也影響msg_ctime成員。
- IPC_RMID:刪除msqid標(biāo)識(shí)的消息隊(duì)列;
調(diào)用返回: 成功返回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
/* 服務(wù)端創(chuàng)建的消息隊(duì)列最后沒(méi)有刪除,我們要使用ipcrm命令來(lái)刪除的 */
/* 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);
}??
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

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