概述
消息隊(duì)列是消息的鏈表恩沽,存放在內(nèi)存中誊稚,由內(nèi)核維護(hù)消息隊(duì)列的特點(diǎn)。
1罗心、消息隊(duì)列中的消息是有類型的里伯。
2、消息隊(duì)列中的消息是有格式的渤闷。
3疾瓮、消息隊(duì)列可以實(shí)現(xiàn)消息的隨機(jī)查詢。消息不一定要以先進(jìn)先出的次序讀取飒箭,編程時可以
按消息的類型讀取狼电。
4蜒灰、消息隊(duì)列允許一個或多個進(jìn)程向它寫入或者讀取消息。
5肩碟、與無名管道强窖、命名管道一樣,從消息隊(duì)列中讀出消息削祈,消息隊(duì)列中對應(yīng)的數(shù)據(jù)都會被刪除翅溺。
6、每個消息隊(duì)列都有消息隊(duì)列標(biāo)識符髓抑,消息隊(duì)列的標(biāo)識符在整個系統(tǒng)中是唯一的咙崎。
7、只有內(nèi)核重啟或人工刪除消息隊(duì)列時吨拍,該消息隊(duì)列才會被刪除褪猛。若不人工刪除消息隊(duì)列,消息隊(duì)列會一直存在于系統(tǒng)中
在ubuntu 某些版本中消息隊(duì)列限制值如下:
每個消息內(nèi)容最多為8K字節(jié)
每個消息隊(duì)列容量最多為16K字節(jié)
系統(tǒng)中消息隊(duì)列個數(shù)最多為1609個
系統(tǒng)中消息個數(shù)最多為16384個
消息隊(duì)列的API
1密末、獲取系統(tǒng)唯一的key值
#include<sys/types.h>
#include<sys/ipc.h>
key_t ftok(const char *pathname ,int proj_id);
功能:
????????獲得項(xiàng)目相關(guān)的唯一的IPC鍵值。
參數(shù):
????????pathname:路徑名
????????proj_id:項(xiàng)目ID跛璧,非0整數(shù)(只有低8位有效)
返回值:
????????成功返回key值严里,失敗返回 -1
2、創(chuàng)建消息隊(duì)列
#include<sys/msg.h>
int msgget(key_t key,int msgflg);
功能:
????????創(chuàng)建一個新的或打開一個已經(jīng)存在的消息隊(duì)列追城。不同的進(jìn)程調(diào)用此函數(shù)刹碾,只要用相同的key值就
????????能得到同一個消息隊(duì)列的標(biāo)識符。
參數(shù):
????????key:IPC鍵值座柱。
????????msgflg:標(biāo)識函數(shù)的行為及消息隊(duì)列的權(quán)限迷帜。
????????????msgflg的取值:
????????????IPC_CREAT:創(chuàng)建消息隊(duì)列。
????????????PC_EXCL:檢測消息隊(duì)列是否存在色洞。
????????????位或權(quán)限位:消息隊(duì)列位或權(quán)限位后可以設(shè)置消息隊(duì)列的訪問權(quán)限戏锹,格式和open函數(shù)的mode_t
????????????一樣,但可執(zhí)行權(quán)限未使用火诸。
返回值:
????????成功:消息隊(duì)列的標(biāo)識符锦针,失敗:返回-1
查看消息隊(duì)列:
ipcs ‐q
刪除消息隊(duì)列
ipcrm ‐q msqid
3、消息隊(duì)列的信息 格式定義
typedefstruct_msg{
????????long mtype; /*消息類型 必須是第一個成員 必須是long類型*/
????????char mtext[100]; /*消息正文 不止一個成員*/
? ??????... /*消息的正文可以有多個成員*/
}MSG;
4置蜀、發(fā)送消息
#include<sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz,int msgflg);
功能:
????????將新消息添加到消息隊(duì)列奈搜。
參數(shù):
????msqid:消息隊(duì)列的標(biāo)識符。
????msgp:待發(fā)送消息結(jié)構(gòu)體的地址盯荤。
????msgsz:消息正文的字節(jié)數(shù)馋吗。
????msgflg:函數(shù)的控制屬性
????????0:msgsnd調(diào)用阻塞直到條件滿足為止。
????????PC_NOWAIT: 若消息沒有立即發(fā)送則調(diào)用該函數(shù)的進(jìn)程會立即返回秋秤。
返回值:
????????成功:0;失敗:返回-1
5宏粤、接收消息
#include<sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp ,size_t msgsz, long msgtyp,int msgflg);
功能:
? ??????從標(biāo)識符為msqid的消息隊(duì)列中接收一個消息脚翘。一旦接收消息成功,則消息在消息隊(duì)列中被刪除商架。參數(shù):
????????msqid:消息隊(duì)列的標(biāo)識符堰怨,代表要從哪個消息列中獲取消息。
????????msgp: 存放消息結(jié)構(gòu)體的地址蛇摸。
????????msgsz:消息正文的字節(jié)數(shù)备图。
????????msgtyp:感興趣消息的類型、可以有以下幾種類型
????????????msgtyp = 0:返回隊(duì)列中的第一個消息
????????????msgtyp > 0:返回隊(duì)列中消息類型為msgtyp的消息
????????????msgtyp < 0:返回隊(duì)列中消息類型值小于或等于msgtyp絕對值的消息赶袄,如果這種消息有若
? ? ? ? ? ? 干個揽涮,則取類型值最小的消息。
? 注意:
? ? ? ? ? 若消息隊(duì)列中有多種類型的消息饿肺,msgrcv獲取消息的時候按消息類型獲取蒋困,不是先進(jìn)先出的。
? ? ? ? ? 在獲取某類型消息的時候敬辣,若隊(duì)列中有多條此類型的消息雪标,則獲取最先添加的消息,即先進(jìn)先出
? ? ? ? ? msgflg:函數(shù)的控制屬性
? ? ? ? ? 0:msgrcv調(diào)用阻塞直到接收消息成功為止溉跃。
? ? ? ? ? MSG_NOERROR:若返回的消息字節(jié)數(shù)比nbytes字節(jié)數(shù)多,則消息就會截短到nbytes字節(jié),且不通知
? ? ? ? ? 消息發(fā)送進(jìn)程村刨。
? ? ? ? ? IPC_NOWAIT:調(diào)用進(jìn)程會立即返回。若沒有收到消息則立即返回-1撰茎。
返回值:
成功返回讀取消息的長度嵌牺,失敗返回-1
總結(jié):
不管是發(fā)送者還是接收者
? ??????ftok 得到唯一的key
????????msgget 創(chuàng)建消息隊(duì)列
發(fā)送者
? ??????MSG msg;
? ??????msg.mtype = 接收感興趣的類型值;
? ??????msgsnd(msg_id,&msg,sizeof(MSG)‐sizeof(long),0);//發(fā)送消息到消息隊(duì)列
接收者
? ??????MSG msg;
? ??????msgrcv(msg_id,&msg,sizeof(MSG)‐sizeof(long),30,0);
????????msgrcv(msg_id,&msg,sizeof(MSG)‐sizeof(long),接收感興趣的類型值,0);
示例代碼
發(fā)送方
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>?
?#include<sys/msg.h>?
?#include<string.h>?
?//定義一個消息類型結(jié)構(gòu)?
?typedef struct MyStruct
{?
? ? ? long mtype; //消息類型?
????? char mtext[64]; //消息正文?
????? char name[32]; //發(fā)送者的姓名?
?}MSG;?
?int main(int argc,char const*argv[])
?{?
?????????//獲取IPC的唯一KEY值?
? ? ? ? ?key_t key = ftok("/", 2021);?
? ? ? ? ?printf("key=%#x\n", key);?
?????????//創(chuàng)建一個消息隊(duì)列?
????????? int msg_id = msgget(key, IPC_CREAT | 0666);?
????????? printf("msg_id=%d\n", msg_id);?
????????? //發(fā)送消息 給lucy‐‐20發(fā)消息?
????????? MSG msg;?
????????? memset(&msg, 0, sizeof(msg));?
????????? msg.mtype = 30;?
????????? strcpy(msg.name, "bob");?
????????? strcpy(msg.mtext, "hello msg");?
????????? msgsnd(msg_id, &msg, sizeof(MSG) ‐ sizeof(long), 0);
????????? return 0;?
?}
接收方
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
//定義一個消息類型結(jié)構(gòu)?
?typedef struct MyStruct
{
????????long mtype; //消息類型
????????char mtext[64]; //消息正文
????????char name[32]; //發(fā)送者的姓名
}MSG;
int main(int argc,char const*argv[])
{
????????//獲取IPC的唯一KEY值??
? ? ? ? key_t key = ftok("/", 2021);
????????printf("key=%#x\n", key);
????????//創(chuàng)建一個消息隊(duì)列
????????int msg_id = msgget(key, IPC_CREAT | 0666);
????????MSG msg;
????????memset(&msg, 0, sizeof(msg));?
????????msgrcv(msg_id, &msg, sizeof(MSG)‐sizeof(long), 20, 0);
? ? ? ? printf("發(fā)送者:%s\n", msg.name);?
? ? ? ? printf("消息:%s\n", msg.mtext);
????????
????????return 0;?
?}
6、消息隊(duì)列的控制
#include<sys/msg.h>
int msgctl(int msqid,int cmd,struct msqid_ds*buf);
功能:
? ??????對消息隊(duì)列進(jìn)行各種控制龄糊,如修改消息隊(duì)列的屬性逆粹,或刪除消息消息隊(duì)列。
參數(shù):
????????msqid:消息隊(duì)列的標(biāo)識符炫惩。
????????cmd:函數(shù)功能的控制僻弹。
????????buf:msqid_ds數(shù)據(jù)類型的地址,用來存放或更改消息隊(duì)列的屬性他嚷。
????????
????????cmd:函數(shù)功能的控制
????????IPC_RMID:刪除由msqid指示的消息隊(duì)列奢方,將它從系統(tǒng)中刪除并破壞相關(guān)數(shù)據(jù)結(jié)構(gòu)。
????????IPC_STAT:將msqid相關(guān)的數(shù)據(jù)結(jié)構(gòu)中各個元素的當(dāng)前值存入到由buf指向的結(jié)構(gòu)中爸舒。
????????IPC_SET:將msqid相關(guān)的數(shù)據(jù)結(jié)構(gòu)中的元素設(shè)置為由buf指向的結(jié)構(gòu)中的對應(yīng)值壮韭。
返回值:
????成功:返回 0;失敗:返回 ‐1