C++ Linux IPC进程通信-消息队列MQ
原文链接:C++ Linux IPC进程通信-消息队列MQ
消息队列库<sys/msg.h>
相比于共享内存和管道,消息队列能够实现指定的消息格式和排序,能实现更复杂的通信
库函数
// 创建消息队列
int msgget(key_t, key, int msgflg); return ID(成功) -1(错误)key为一个标记内存的关键字,可用自己指定,也可以用ftok函数转文件名为key,msgflg标志包括IPC_CREAT(创建)|IPC_EXCL(存在则报错)//发送
int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);return 0(成功) -1(错误) msgflg标志: IPC_NOWAIT(消息队列已经满了立即返回不阻塞),MSG_NOERROR(超过限制长度截断)
msg_ptr指向的对象是一个结构体:
struct msg{ long int message_type; //队列需要的消息类别//其他需要通信的数据类型
}; //接收
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg); return 0(成功) -1(错误) msgtype: >0接受指定类型数据 =0解释第一个数据 <0接受小于其绝对值类型的数据msgflg标志同样实现接收不阻塞和超长截断// 控制
int msgctl(int msgid, int command, struct msgid_ds *buf);
与共享内存的shmid_ds类似,对消息队列参数控制
实例:使用消息队列 子进程发送一个自增数据,父进程接收并输出
#include <iostream>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <cstring>using namespace std;template<typename T>
void check(const char* er, const T& a, const T& b) {if (a == b) {perror(er);exit(EXIT_FAILURE);}
}struct Msg{long msg_type;int cnt;
};int main()
{int fd=open("name_msg",O_CREAT|O_RDWR,0666);check(string("open").c_str(),fd,-1);key_t k=ftok("name_msg",'A');check(string("ftok").c_str(),k,-1);int ipcid=msgget(k,IPC_CREAT|0666);check(string("msgget").c_str(),ipcid,-1);Msg cntmsg;cntmsg.msg_type=1;cntmsg.cnt=0;pid_t cpid=fork();if(cpid==-1){check(string("fork").c_str(),cpid,-1);}else if(cpid>0){for(int i=0;i<3;i++){int r=msgrcv(ipcid,&cntmsg,sizeof(cntmsg),1,0);check(string("msgrcv").c_str(),r,-1);cout<<"parent get cnt="<<cntmsg.cnt<<"\n";}}else{for(int i=0;i<3;i++){cntmsg.cnt++;cout<<"child send cnt="<<cntmsg.cnt<<"\n";int r=msgsnd(ipcid,&cntmsg,sizeof(cntmsg),0);check(string("msgsnd").c_str(),r,-1);}}return 0;
}
特点(详细参考链接)
优点
- 解耦: 不用消息队列MQ,在多个连接条件下,主机需要维护每个进程的消息,增加主机的消耗. 采用消息队列,其他用户有需求可以直接从消息队列里自己获取.
- 异步: 当然消息队列存在实现了异步通信,不需要等待了.
- 缓冲: 对超量的请求使用MQ减小并发量,提高系统稳定性
缺点
MQ的复杂度较高,维护成本增加.如果MQ挂了,主服务直接挂了.