三、Linux系统编程:进程间的通信(IPC)之消息队列

3 IPC(进程间通信)消息队列

消息队列(Message queue)是一种进程间通信或同一进程的不同线程间的通信方式,软件的贮列用来处理一系列的输入,通常是来自用户。

3.1 背景

管道和套接字比较适合两三个进程之间的通信,如果进程成倍增加,管道和套接字的数量也会阶乘级的增加,管理也非常复杂麻烦,于是出现了消息队列。

3.2 POSIX 消息队列

在这里插入图片描述

3.3 查看

  • POSIX消息队列预览:man mq_overview
  • 查看POSIX消息队列:ls /dev/mqueue
  • cat /dev/mqueue/PIC名字

3.4 接口

头文件:mqueue.h
库:librt.so(real time)

3.5 结构体

struct mq_attr消息队列属性

成员含义说明
mq_flags标志mq_open时被初始化,在mq_setattr设置,其值为0或者O_NONBLOCK
mq_maxmsg队列的消息个数最大值只能在mq_open时被初始化
mq_msgsize队列每个消息长度的最大值只能在mq_open时被初始化
mq_curmsgs当前队列消息个数mq_getattr获取

3.6 函数

POSIX 消息队列主要有八个操作

操作函数
创建消息队列mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr)
删除消息队列int mq_unlink(const char *name)
打开消息队列mqd_t mq_open(const char *name, int oflag)
关闭消息队列int mq_close(mqd_t mqdes)
发送消息int mq_send(mqd_t mqdes, const char *msg_ptr,size_t msg_len, unsigned msg_prio)
接收消息ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,size_t msg_len, unsigned *msg_prio)
设置消息队列属性int mq_setattr(mqd_t mqdes, struct mq_attr *newattr,struct mq_attr *oldattr)
获取消息队列属性int mq_getattr(mqd_t mqdes, struct mq_attr *attr)

注:消息队列操作与文件读写操作非常相似

3.6.1 创建消息堆列

mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr)
  • 参数
参数含义
nameposix IPC名字,格式为/somename
oflag标志
mode权限
attr队列属性,阻塞attr.mq_flag = 0;非阻塞attr.mq_flag = NONBLOCK
  • 标志
标志作用
O_CREAT没有该对象则创建
O_EXCL如果O_CREAT指定,但name不存在,就返回错误
O_NONBLOCK以非阻塞方式打开消息队列
O_RDONLY只读
O_RDWR读写
O_WRONLY只写
  • 权限
权限作用
S_IWUSR用户/属主写
S_IRUSR用户/属主读
S_IWGRP组成员写
S_IRGRP组成员读
S_IWOTH其他用户写
S_IROTH其他用户读
  • 返回值
返回值含义
-1出错
其他消息队列描述符
  • 注意
    编译时需要加上 -lrt

3.6.2 删除消息队列

int mq_unlink(const char *name)
  • 参数
    name :posix IPC名字
  • 返回值
返回值含义
-1出错
0成功

3.6.3 打开消息队列

mqd_t mq_open(const char *name, int oflag)
  • 参数
参数含义
nameposix IPC名字
oflag标志,O_RDONLY只读;O_RDWR读写;O_WRONLY只写
  • 返回值
返回值含义
-1出错
其他消息队列描述符

3.6.4 关闭消息队列

int mq_close(mqd_t mqdes)
  • 参数
    mqdes :消息队列描述符

  • 返回值

返回值含义
-1出错
0成功
  • 注意
    mq_close()和文件的close()类似,关闭后,消息队列并不从系统中删除。
    一个进程结束,会自动关闭打开着的消息队列。

3.6.5 发送消息

int mq_send(mqd_t mqdes, const char *msg_ptr,size_t msg_len, unsigned msg_prio)
  • 参数
参数含义
msg_ptr消息的指针。
msg_len消息长度,不能大于属性值mq_msgsize的值
msg_prio优先级,小于MQ_PRIO_MAX,数值越大,优先级越高
  • 注意
    消息在队列中将按照优先级大小顺序来排列消息
    消息队列已满,mq_send()函数将阻塞,直到有可用空间再次允许放置消息。
    如果O_NONBLOCK被指定,mq_send()那么将不会阻塞,而是返回EAGAIN错误。

3.6.6 接收消息

ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,size_t msg_len, unsigned *msg_prio)
  • 参数
参数含义
msg_ptr消息的指针。
msg_len消息长度,不能大于属性值mq_msgsize的值
msg_prio优先级,消息在队列中将按照优先级大小顺序来排列消息
  • 返回值
返回值含义
-1出错
正数接收到的消息长度
  • 注意
    POSIX消息队列在调用mq_receive()时总是返回队列中最高优先级的最早消息。
    如果队列空,mq_receive()函数将阻塞,直到消息队列中有新的消息。
    如果O_NONBLOCK被指定,mq_receive()那么将不会阻塞,而是返回EAGAIN错误。

3.6.7 设置消息队列属性

int mq_setattr(mqd_t mqdes, struct mq_attr *newattr,struct mq_attr *oldattr);
  • 参数
参数含义
mqdes消息队列描述符
newattr新属性,只能设置mq_flags:0:NONBLOCK
oldattr旧属性
  • 返回值
返回值含义
-1出错
0成功

3.6.8 获取消息队列属性

int mq_getattr(mqd_t mqdes, struct mq_attr *attr)
  • 参数
参数含义
mqdes消息队列描述符
attr属性
  • 返回值
返回值含义
-1出错
0成功
  • 注意
    mq_setattr()可以设置的属性只有mq_flags,用来设置或清除消息队列的非阻塞标志。newattr结构的其他属性被忽略。
    mq_maxmsgmq_msgsize属性只能在创建消息队列时通过mq_open()来设置。
    mq_open()只会设置该两个属性,忽略另外两个属性。
    mq_curmsgs属性只能被获取而不能被设置。

3.7 实例: 创建POSIX消息队列,实现基本的消息收发

  • create_mq.cpp
#include <mqueue.h>
#include <cstdio>
#include <iostream>
using namespace std;
int main(int argc,char** argv){
    mq_attr attr;
    attr.mq_maxmsg = 100;
    attr.mq_msgsize = 100;
    cout << argv[1] << endl;
    mqd_t fd = mq_open(argv[1],O_CREAT,0644,&attr);
    if(-1 == fd){
    	perror("mq_open error");
    }
    return 0;
}
  • write_mq.cpp
#include <mqueue.h>
#include <iostream>
using namespace std;
int main(int argc,char** argv){
    mqd_t fd = mq_open(argv[1],O_WRONLY);
    if(-1 == fd){
    	perror("mq_open error");
	return 1;
    }
    string msg;
    cin >> msg;
    mq_send(fd,msg.c_str(),msg.size()+1,0);
    mq_close(fd);
}
  • read_mq.cpp
#include <iostream>
#include <mqueue.h>
using namespace std;
int main(int argc,char** argv){
    mqd_t fd = mq_open(argv[1],O_RDONLY);
    if(-1 == fd){
    	perror("mq_open error");
    }
    char buffer[1024] = {0};
    unsigned int p;
    mq_receive(fd,buffer,sizeof(buffer),&p);
    cout << buffer << endl;
    mq_close(fd);
}

步骤:
1)通过该程序创建一个类似通道的交互文件,g++ create_mq.cpp -lrt
2)执行./a.out /abc生成一个名为abc的通道,目录位于/dev/mqueue
3)执行:./write_mq /abc 发送
4)执行:另一shell窗口./ read_mq /abc 接收

[root@localhost 3]# ./write /abc
a   
[root@localhost 3]# ./write /abc
b
[root@localhost 3]# ./write /abc
c
[root@localhost 3]# ./write /abc
1
[root@localhost 3]# ./write /abc
2
[root@localhost 3]# ./write /abc
3
[root@localhost 3]# 
...
...
[root@localhost 3]# ./read /abc
a
[root@localhost 3]# ./read /abc
b
[root@localhost 3]# 
[root@localhost 3]# ./read /abc
c
[root@localhost 3]# ./read /abc
1
[root@localhost 3]# ./read /abc
2
[root@localhost 3]# ./read /abc
3
[root@localhost 3]#
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值