天天看點

Linux程序通信——消息隊列消息隊列概述消息隊列發送端消息隊列接收端消息隊列互相發送接收

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");


}

           

效果如下:

Linux程式通信——消息隊列消息隊列概述消息隊列發送端消息隊列接收端消息隊列互相發送接收

當同時運作兩個程式時,消息就能接收

補充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;
}

           
Linux程式通信——消息隊列消息隊列概述消息隊列發送端消息隊列接收端消息隊列互相發送接收

兩個程序通信可以使用相同的key值但接收和發送通道的類型要不同!

繼續閱讀