天天看点

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值但接收和发送通道的类型要不同!

继续阅读