栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

三、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_maxmsg和mq_msgsize属性只能在创建消息队列时通过mq_open()来设置。
    mq_open()只会设置该两个属性,忽略另外两个属性。
    mq_curmsgs属性只能被获取而不能被设置。
3.7 实例: 创建POSIX消息队列,实现基本的消息收发
  • create_mq.cpp
#include 
#include 
#include 
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 
#include 
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 
#include 
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]#
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/928125.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号