0%

C++ Linux IPC进程通信-消息队列MQ

原文链接:C++ Linux IPC进程通信-消息队列MQ

消息队列库<sys/msg.h>

相比于共享内存和管道,消息队列能够实现指定的消息格式和排序,能实现更复杂的通信

库函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 创建消息队列
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类似,对消息队列参数控制

实例:使用消息队列 子进程发送一个自增数据,父进程接收并输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

#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;
}

特点(详细参考链接)

优点

  1. 解耦: 不用消息队列MQ,在多个连接条件下,主机需要维护每个进程的消息,增加主机的消耗. 采用消息队列,其他用户有需求可以直接从消息队列里自己获取.
  2. 异步: 当然消息队列存在实现了异步通信,不需要等待了.
  3. 缓冲: 对超量的请求使用MQ减小并发量,提高系统稳定性

缺点

MQ的复杂度较高,维护成本增加.如果MQ挂了,主服务直接挂了.