Linux程序通信——消息隊列
- 消息隊列概述
- 消息隊列發送端
- 消息隊列接收端
-
- 補充key值作用
- 消息隊列互相發送接收
消息隊列概述
消息隊列是存在Linux核心中,以連結清單形式來存消息
一個消息隊列由一個辨別符(即隊列ID)來辨別。
使用者程序可以向消息隊列添加消息,也可以向消息隊列讀取消息。
特點
消息隊列是面向記錄的,其中的消息具有特定的格式(結構體儲存)
消息隊列獨立于發送與接收程序,哪怕程序退出後消息還會儲存
消息隊列中的消息是可以任意讀取的,可以按照類型來讀取
一般形式如下:
// 建立或打開消息隊列:成功傳回隊列ID,失敗傳回-1
int msgget(key_t key, int flag);
// 添加消息:成功傳回0,失敗傳回-1
int msgsnd(int msqid, const void *ptr, size_t size, int flag);
// 讀取消息:成功傳回消息資料的長度,失敗傳回-1
int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);
// 控制消息隊列:成功傳回0,失敗傳回-1
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
消息隊列發送端
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};//消息隊列所用結構體
int main()
{
struct msgbuf sendbuf = {111,"this is send program!!!"};//消息類型與發送内容
key_t key;
key = ftok(".",'30');//擷取IPC鍵值
if(key<0){
printf("creat key number fail!\n");
}//
printf("%x\n",key);
int msgid = msgget(key, IPC_CREAT|0777);//建立消息隊列
if(msgid==-1){
printf("creat que error!\n");
perror("why");
}
printf("%d\n",msgid);
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);//發送消息
msgctl(msgid, IPC_RMID,NULL);//删除隊列
return 0;
}
我們将
“this is send programm!!!”
發送到消息隊列中
消息隊列接收端
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
struct msgbuf readbuf;
key_t key;
key = ftok(".",'1');
int msgid = msgget(key, IPC_CREAT|0777);
if(msgid==-1){
printf("creat que error!\n");
perror("why");
}
msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),111,0);//一樣的鍵值和類型
printf("%s\n",readbuf.mtext);
printf("get success\n");
}
效果如下:
當同時運作兩個程式時,消息就能接收
補充key值作用
程序間通信(IPC)
有兩個東西可以辨別一個IPC結構:辨別符(ID)和鍵(key)。
鍵值(ID)
ID是IPC結構的内部名,用來確定使用同一個通訊通道(比如說這個通訊通道就是消息隊列)。内部即在程序内部使用,這樣的辨別方法是不能支援程序間通信的。
辨別符(key)
key就是IPC結構的外部名。當多個程序,針對同一個key調用get函數(msgget等),這些程序得到的ID其實是辨別了同一個IPC結構。多個程序間就可以通過這個IPC結構通信。
消息隊列互相發送接收
我們分為夫妻兩個程序
互相發送消息
夫程序如下:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
struct msgbuf readbuf;
struct msgbuf sendbuf = {520,"form husband:you are my wife!love you so much"};
key_t key;
key = ftok(".",30);
if(key<0){
printf("creat key number fail!\n");
}
printf("%x\n",key);
int msgid = msgget(key, IPC_CREAT|0777);
if(msgid==-1){
printf("creat que error!\n");
perror("why");
}
printf("%d\n",msgid);
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);
msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),1314,0);
printf("%s\n",readbuf.mtext);
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
妻程序
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>
//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
struct msgbuf readbuf;
struct msgbuf sendbuf = {1314,"form wife:you are my husband!love you so much"};
key_t key;
key = ftok(".",30);
if(key<0){
printf("creat key number fail!\n");
}
printf("%x\n",key);
int msgid = msgget(key, IPC_CREAT|0777);
if(msgid==-1){
printf("creat que error!\n");
perror("why");
}
printf("%d\n",msgid);
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgsnd(msgid,&sendbuf,strlen(sendbuf.mtext),0);
msgrcv(msgid,&readbuf,sizeof(readbuf.mtext),520,0);
printf("%s\n",readbuf.mtext);
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
兩個程序通信可以使用相同的key值但接收和發送通道的類型要不同!