本文主要通過消息隊列的編程實例來加深對消息隊列的理解.
一、消息隊列之創建
創建一個消息隊列,需要用到一個函數:
#include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h> int msgget(key_t key,int msgflg);
key:需要調用ftok函數來獲取.
msgflg:IPC_CREAT,不存在則創建,存在則返回已有的qid.
IPC_CREAT|IPC_EXCL,不存在則創建,存在則返回出錯.
ftok函數原型如下:
#include<sys/types.h> #include<sys/ipc.h> key_t ftok(const char*pathname,int proj_id);
ftok函數通過給定的路徑名稱取得其stat結構中的st_dev字段和st_info字段,然后將它們和項目id結合起來,然后產生一個鍵返回.
為了方便使用,我們將創建消息隊列與獲取消息隊列封裝為兩個函數:
//創建與打開消息隊列公共函數 int MessageCommon(key_t key,int flag){ int ret = 0; if((ret=msgget(key,flag))==-1){ perror("msgget:"); exit(-1); } return ret; } //創建全新的消息隊列(服務端) int CreateMessage(key_t qid){ //消息隊列也是具有權限結構的,因此在創建時給666權限 return MessageCommon(qid,IPC_CREAT|IPC_EXCL|0666); } //打開已有的消息隊列(客戶端) int GetMessage(key_t qid){ return MessageCommon(qid,IPC_CREAT); }
二、消息隊列之發送消息
使用消息隊列發送消息用到了一個函數和一個結構體:
#include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h> int msgsnd(int msgid,const void* msgp,size_t magsz,int msgflg);
msgid:消息隊列標識符
msgp:發送的消息結構體指針
msgsz:結構體中消息的大小(不是整個結構體的大小)
msgflg:IPC_NOWAIT,消息隊列滿時返回-1
0,消息隊列滿時阻塞.
在通過msgsnd發送數據時,需要一個結構體來存放所發送的數據,及發送者的類型.
struct msgbuf{ long mtype; //消息類型,由用戶自定義 char mtext[1024];//發送的消息(長度、類型可以自行指定) }
因此,我們將發送消息也做一層封裝:
//發送消息 void SendMessage(int msgid,const char* msg,int who){ msgbuf buf; buf.mtype = who; //消息類型 strcpy(buf.mtext,msg); //消息內容 if(msgsnd(msgid,&buf,sizeof(buf.mtext),0) == -1){ perror("msgsnd"); DestoryMessage(msgid); exit(-2); } }
三、消息隊列之接收消息
消息隊列接收消息的函數原型如下:
#include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h> ssize_t msgrcv(int qid,void *msgp,size_t msgsz,long msgtyp,int msgflg);
qid:消息隊列的標識符
msgp:消息結構體指針
msgsz:消息內容大小
msgtyp:消息類型
msgflg:同上
封裝之后的代碼如下:
void ReceiveMessage(int msgid,char* msg,int who){ msgbuf buf; if(msgrcv(msgid,&buf,sizeof(buf.mtext),who,0)==-1){ perror("msgrcv"); DestoryMessage(msgid); exit(-3); } strcpy(msg,buf.mtext); }
四、消息隊列的刪除
其函數原型如下:
#include<sys/type.h> #include<sys/ipc.h> #Include<sys/msg.h> int msgctl(int msgid,int cmd,struct msgid_ds *buf);
msgid:消息隊列標識符
cmd:所要采取的命令.IPC_RMID刪除消息隊列
buf:權限信息
封裝后函數如下:
//消息隊列的刪除 void DestoryMessage(int msgid){ if(msgctl(msgid,IPC_RMID,NULL) == -1){ perror("msgctl"); exit(-4); } }
以上便是消息隊列的基本操作,關於消息隊列通信實例為節省文章篇幅,請移步至:https://github.com/gaoxiaodiao/Linux/tree/master/LinuxCode/MessageQueue