Linux C++实现进程间通信——消息队列(结合protobuf)
创始人
2025-05-31 14:32:52

基本知识

基本知识介绍参考:https://mp.weixin.qq.com/s/oSXUJiLT_qJoW4xk-zAf6g

进程间通信简称IPC(Inter process communication),进程间通信就是在不同进程之间传播或交换信息,通常采用的方法有共享内存、信号量、管道和消息队列等。

消息队列本质是一个存储消息的链表,这些消息具有特定的格式及特定优先级。消息队列是随内核持续的,只有在内核重启或删除一个消息队列时,该消息队列才会真正地被删除。

API函数

1.获取键值。

 key_t ftok ( char *pathname, char proj_id );
  • 每个消息队列都要在系统范围内有对应的唯一键值。
  • 其中参数fname是指定的文件名,这个文件必须是存在的而且可以访问的。
  • id是子序号,它是一个8bit的整数。即范围是0~255。当函数执行成功,则会返回key_t键值,否则返回-1。
  • 在一般的UNIX中,通常是将文件的索引节点取出,然后在前面加上子序号就得到key_t的值。

2. 创建或打开消息队列

int msgget(key_t key ,int msgflg ); 
  • 与其他的IPC机制一样,程序必须提供一个键来命名某个特定的消息队列。
  • msgflg是一个权限标志,表示消息队列的访问权限,它与文件的访问权限一样。IPC_EXCL和IPC_CREAT一起使用,如果对应键值的消息队列已经存在,则出错返回-1。IPC_CREAT|0666 表示如果不存在则创建,并且给权限。

3. 发送消息

int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
  • msg_ptr是一个指向准备发送消息的指针,但是消息的数据结构却有一定的要求,消息结构要定义如下格式:

  • msg_ptr是一个指向准备发送消息的指针,但是消息的数据结构却有一定的要求,消息结构要定义如下格式:
    在这里插入图片描述

  • msg_sz为要发送消息的大小,不含消息类型占用字节。

  • msgflg为0表示当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列。

  • msg_sz为要发送消息的大小,不含消息类型占用字节。

  • msgflg为0表示当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列。
    4. 接收消息

int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);
  • msgflg为0表示阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待。
    5. 控制消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
  • 控制消息队列,成功返回0,失败返回-1

代码示例

代码放这了,可以直接下载测试

git clone https://github.com/zlshao/MQ_demo.git
sudo chmod 777 run.sh
./run.sh

会产生两个可执行文件,开两个终端分别运行就可以了。

下面简单讲解一下代码

  1. 创建一个msg.proto,里面存放要通过消息队列传输的数据正文,我放了一个id和一个文本消息text。关于protobuf的具体讲解可以参考以下链接:
    链接1-protobuf
    链接2-protobuf
syntax = "proto2";
package messageQ;message Msgbuf{optional int64 id=1;optional string text=2;}
  1. send.cpp
#include
#include
#include
#include
#include
#include
using namespace std;#include"msg.pb.h"struct Msgstruct{long type; //类型是固定的,必须要有的char data[256]; //这里存放序列化后的proto消息!!!
};int main(){messageQ::Msgbuf sendData;//设置需要发送的消息,包括ID和textsendData.set_id(111); sendData.set_text("This is a protobuf message");//序列化为string发送。其实也可以直接序列化为数组string str=sendData.SerializePartialAsString();Msgstruct writeMsg;writeMsg.type=888; //888为消息类型strcpy(writeMsg.data,str.c_str());int msgID=msgget(0x1234,IPC_CREAT|0777);if(msgID==-1){cout<<"Failure!"<
  1. receive.cpp
#include 
#include 
#include 
#include 
#include 
#include#include"msg.pb.h"using namespace std;struct Msgstruct{long type;char data[256];
};int main(){Msgstruct readMsg;int msgID=msgget(0x1234,IPC_CREAT|0777);if(msgID==-1){cout<<"failure!"<
  1. 运行效果:
    在这里插入图片描述
    在这里插入图片描述

相关内容

热门资讯

透视脚本!aapoker辅助器... 透视脚本!aapoker辅助器是真的(透视辅助)WEPOKER透视选牌,介绍教程(有挂教学)是一款具...
亲测!揭秘!友乐麻将外挂辅助器... 您好:友乐麻将这款游戏可以开挂的,确实是有挂的,很多玩家在这款游戏中打牌都会发现很多用户的牌特别好,...
科普实测“吉祥七公透视挂辅助安... 您好:吉祥七公这款游戏可以开挂,确实是有挂的,需要软件加微信【5951795】,很多玩家在吉祥七公这...
盘点一款“开心联盟到底有挂吗”... 您好,开心联盟这款游戏可以开挂的,确实是有挂的,通过微信【3696223】很多玩家在这款游戏中打牌都...
透视脚本!aapoker辅助器... 透视脚本!aapoker辅助器是真的(透视辅助)透视选牌,介绍教程(有挂教学)亲,有的,ai轻松简单...