Linux进程通信——消息队列

消息队列概述

消息队列是存在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值但接收和发送通道的类型要不同!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pg_hj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值