Qt implements IPC inter-process communication-mqueue message queue

Introduction

This article introduces QT's use of mqueue message queue to achieve inter-process communication under linux;
header file #include <mqueue.h> needs to be included;
pro file add compilation option: LIBS += -lrt;
message queue feature: you can set the maximum number of messages, The maximum number of bytes of each message. Multiple messages can be written to the message queue. If the other process reads one, the message queue will delete one.

Interface introduction

1. Message queue structure mq_attr

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

2. Get the attributes of the message queue.
Before sending and receiving messages, a process needs to understand the attributes of the message object, such as the maximum length of the message. In order to set the buffer size for receiving and sending.

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

Mqdes: The descriptor obtained when the message queue is opened.
Attr: Pointer to the structure struct mq_attr, used to obtain the four attributes of the message queue.

3. Setting the attributes of the message queue
We can set the attributes of the message queue. Actually, only the flag flag can be set to indicate whether the process of receiving messages continues to wait on the queue when there is no message in the queue.

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

Mqdes: The descriptor obtained when the message queue is opened.
Attr: Pointer to the structure struct mq_attr, used to obtain the maximum number of messages and the maximum message length of the message queue. Put it in the mq_maxmsg and mq_msgsize of the data structure.

4. Sending a message After the
process opens the message queue, you can use the following function to send a message

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

mqdes: The descriptor obtained when opening the message queue.
ptr: Pointer to the sending buffer, the sending buffer stores the data to be sent.
Len: The length of the data to be sent.
prio: the priority of the message; it is a number less than MQ_PRIO_MAX, the larger the value, the higher the priority.
The POSIX message queue always returns the oldest message with the highest priority in the queue when mq_receive is called. If the message does not need to set the priority, you can set prio to 0 in mq_send and set prio in mq_receive to NULL. Return value: if sending is successful, it returns 0, if it fails, it returns -1.

5. Receiving messages After the
process opens the message queue, you can use the following functions to receive messages.

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

mqdes: The descriptor obtained when opening the message queue.
ptr: Pointer to the receiving buffer. The receive buffer is used to store the received messages.
Len: The length of the receiving buffer. len cannot be less than mq_msgsize, otherwise it will return EMSGSIZE
prio: the priority of the message; it is a number less than MQ_PRIO_MAX, the larger the value, the higher the priority. The POSIX message queue always returns the oldest message with the highest priority in the queue when mq_receive is called. If the message does not need to set the priority, you can set prio to 0 in mq_send and set prio in mq_receive to NULL. Return value: If receiving is successful, it returns 0, if it fails, it returns -1.

6. The message queue is closed

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

7, delete the message queue

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

When a process has not closed this message queue, when mq_unlink is called, the queue will not be deleted immediately. When the last process closes the queue, the queue will be deleted

Code

The example creates two new projects, starts two applications, uses the message queue to communicate, and the interface function prototype is introduced in the note:
project A
widget_pa.h

#ifndef WIDGET_PA_H
#define WIDGET_PA_H

#include <QWidget>
/**
  *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 <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <mqueue.h>
#include <QThread>
#include <QTextCodec>
#include <QDebug>

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

Project B
widget_pb.h

#ifndef WIDGET_PB_H
#define WIDGET_PB_H

#include <QWidget>
#include <QThread>

#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 <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <mqueue.h>

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

Show results

Insert picture description here

Message queue file

After the message queue is created, there will be a message queue file in the /dev/mqueue folder;
Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_40355471/article/details/113178838