Qt实现IPC进程间通信

您所在的位置:网站首页 qt进程间通信 Qt实现IPC进程间通信

Qt实现IPC进程间通信

2023-10-21 02:54| 来源: 网络整理| 查看: 265

简介

本文介绍QT在linux下使用mqueue消息队列实现进程间通信; 需包含头文件#include ; pro文件添加编译选项:LIBS += -lrt; 消息队列特征:可以设置最大消息个数、每个消息最大字节数,可以往消息队列写入多条消息,other进程读取一条,消息队列就删除一条。

接口介绍

1、消息队列结构体mq_attr

struct mq_attr { long mq_flags; // 0或者O_NONBLOCK long mq_maxmsg; //队列中包含的消息数的最大限制数 long mq_msgsize; //每个消息大小的最大限制数 long mq_curmsgs; //当前队列中的消息数 }

2、获取消息队列的属性 一个进程在发送和接收消息之前,需要了解消息对象的属性,如消息的最大长度。以便设定接收和发送的buffer大小。

mqd_t mq_getattr(mqd_t mqdes, struct mq_attr *attr);

Mqdes:打开消息队列时获取的描述符。 Attr:指向结构struct mq_attr的指针,用来获取消息队列的四个属性。

3、设置消息队列属性 我们可以设置消息队列的属性,实际只能设置flag标志,说明队列中没有消息时,接收消息的进程是否在队列上继续等待。

mqd_t mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);

Mqdes:打开消息队列时获取的描述符。 Attr:指向结构struct mq_attr的指针,用来获取消息队列的最大消息个数和最大消息长度。放到数据结构的mq_maxmsg和mq_msgsize中。

4、发送消息 进程在打开消息队列后,可以使用下面的函数发送消息

int mq_send(mqd_t mqdes, const char *ptr, size_t len, unsigned int prio);

mqdes: 打开消息队列时获得的描述符。 ptr: 指向发送缓冲区的指针,发送缓冲区存放了要发送的数据。 Len: 要发送的数据的长度。 prio :消息的优先级;它是一个小于 MQ_PRIO_MAX 的数,数值越大,优先级越高。 POSIX 消息队列在调用 mq_receive 时总是返回队列中 最高优先级的最早消息 。如果消息不需要设定优先级,那么可以在 mq_send 是置 prio 为 0 , mq_receive 的 prio 置为 NULL 。 返回值:发送成功,返回0,失败,返回-1.

5、接收消息 进程在打开消息队列后,可以使用下面的函数接收消息。

//如果mq_flags设置了O_NONBLOCK参数,则读取失败后,会立即返回-1,不会阻塞 ssize_t mq_receive(mqd_t mqdes, char *ptr, size_t len, unsigned int *prio);

mqdes: 打开消息队列时获得的描述符。 ptr: 指向接收缓冲区的指针。接收缓冲区用来存放收到的消息。 Len: 接收缓冲区的长度。 len不能小于mq_msgsize,否则会返回EMSGSIZE prio :消息的优先级;它是一个小于 MQ_PRIO_MAX 的数,数值越大,优先级越高。 POSIX 消息队列在调用 mq_receive 时总是返回队列中 最高优先级的最早消息 。如果消息不需要设定优先级,那么可以在 mq_send 是置 prio 为 0 , mq_receive 的 prio 置为 NULL 。 返回值: 接收成功,返回0,失败,返回-1.

6、消息队列关闭

mqd_t mq_close(mqd_t mqdes);//关闭消息队列,但不能删除它 成功返回0,失败返回-1

7、删除消息队列

mqd_t mq_unlink(const char *name); //成功返回0,失败返回-1

当某个进程还没有关闭此消息队列时,调用mq_unlink时,不会马上删除队列,当最后一个进程关闭队列时,该队列被删除

代码实现

示例新建两个工程,启动两个应用程序,使用消息队列进行通信,接口函数原型介绍见注释: 工程A widget_pa.h

#ifndef WIDGET_PA_H #define WIDGET_PA_H #include /** *s_irusr 允许文件的所有者读取它。 *s_iwusr 允许文件的所有者写入它。 *s_irgrp 允许文件的组读取它。 *s_iwgrp 允许文件的组写入它。 */ #define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) namespace Ui { class Widget_pa; } class Widget_pa : public QWidget { Q_OBJECT public: explicit Widget_pa(QWidget *parent = 0); ~Widget_pa(); private slots: void on_pushButton_clicked(); private: Ui::Widget_pa *ui; signals: }; #endif

widget_pa.cpp

#include "widget_pa.h" #include "ui_widget_pa.h" #include #include #include #include #include #include #include #include Widget_pa::Widget_pa(QWidget *parent) : QWidget(parent), ui(new Ui::Widget_pa) { ui->setupUi(this); } Widget_pa::~Widget_pa() { //4、删除消息队列文件 mq_unlink("/mq_test"); delete ui; } //发送数据 void Widget_pa::on_pushButton_clicked() { char buf[128]; memset(buf,0,sizeof(buf)); /** * @brief mq_attr消息队列结构体 * long mq_flags; // 0或者O_NONBLOCK * long mq_maxmsg; //队列中包含的消息数的最大限制数 * long mq_msgsize; //每个消息大小的最大限制数 * long mq_curmsgs; //当前队列中的消息数 */ struct mq_attr attr; attr.mq_maxmsg = 10; //最大消息10个 attr.mq_msgsize = 128; //每个消息限制大小128字节 attr.mq_flags = 0; /** * @brief 1、创建一个新的消息队列或打开一个已存在的消息的队列 * mqd_t:返回值为int型,消息队列序号 * "/mq_test":消息队列名称 * O_CREAT|O_RDWR:文件属性,类似open文件的选项,O_CREAT(若此文件不存在则创建它),O_RDWR(读、写打开) * FILE_MODE:文件权限 * &attr:mq_attr消息队列结构体 */ mqd_t mqd = mq_open("/mq_test", O_CREAT|O_RDWR, FILE_MODE, &attr); if(-1 == mqd) { perror("mq_open error"); return; } memcpy(buf,ui->textEdit->toPlainText().toLocal8Bit().data(),sizeof(buf)); //2、发送消息 int ret = mq_send(mqd, buf, strlen(buf), 2); if(ret == -1) { perror("mq_send error"); } //3、关闭消息队列文件描述,但不删除,mqd参数:消息队列序号 mq_close(mqd); }

工程B widget_pb.h

#ifndef WIDGET_PB_H #define WIDGET_PB_H #include #include #define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) namespace Ui { class Widget_pb; } class Widget_pb : public QWidget { Q_OBJECT public: explicit Widget_pb(QWidget *parent = 0); ~Widget_pb(); private slots: void on_pushButton_clicked(); private: Ui::Widget_pb *ui; }; #endif // WIDGET_PB_H

widget_pb.cpp

#include "widget_pb.h" #include "ui_widget_pb.h" #include #include #include #include #include Widget_pb::Widget_pb(QWidget *parent) : QWidget(parent), ui(new Ui::Widget_pb) { ui->setupUi(this); } Widget_pb::~Widget_pb() { delete ui; } void Widget_pb::on_pushButton_clicked() { int ret; char buf[128]; memset(buf,0,sizeof(buf)); unsigned int prio=0; struct mq_attr attr; attr.mq_maxmsg = 10; attr.mq_msgsize = 128; attr.mq_flags = 0; //1、创建或打开消息队列 mqd_t mqd = mq_open("/mq_test", O_CREAT|O_RDWR|O_NONBLOCK, FILE_MODE, &attr); if(-1 == mqd) { perror("mq_open error"); return; } //2、接收消息 ret = mq_receive(mqd, buf, sizeof(buf), &prio); if (ret !=-1) { QString str = QString("ret=%1,read:%2").arg(QString::number(ret)).arg(buf); ui->textEdit->append(str); } //3、关闭消息队列 mq_close(mqd); } 效果展示

在这里插入图片描述

消息队列文件

创建消息队列后,在/dev/mqueue文件夹下会有消息队列文件; 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3