Qt implementa fila de mensagens de comunicação entre processos IPC

Introdução

Este artigo apresenta o uso da fila de mensagens mqueue pelo QT para obter comunicação entre processos no Linux;
arquivo de cabeçalho #include <mqueue.h> precisa ser incluído;
arquivo pro adicionar opção de compilação: LIBS + = -lrt;
recurso de fila de mensagens: você pode definir o número máximo de mensagens, O número máximo de bytes de cada mensagem. Várias mensagens podem ser gravadas na fila de mensagens. Se o outro processo ler uma, a fila de mensagens excluirá uma.

Introdução à interface

1. Estrutura da fila de mensagens mq_attr

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

2. Obtenha os atributos da fila de mensagens
Antes de enviar e receber mensagens, um processo precisa entender os atributos do objeto da mensagem, como o comprimento máximo da mensagem. Para definir o tamanho do buffer para recebimento e envio.

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

Mqdes: O descritor obtido quando a fila de mensagens é aberta.
Attr: Ponteiro para a estrutura struct mq_attr, usado para obter os quatro atributos da fila de mensagens.

3. Definindo os atributos da fila de mensagens
Podemos definir os atributos da fila de mensagens. Na verdade, apenas o flag flag pode ser definido para indicar se o processo de recebimento de mensagens continua esperando na fila quando não há mensagem na fila .

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

Mqdes: O descritor obtido quando a fila de mensagens é aberta.
Attr: Ponteiro para a estrutura struct mq_attr, usado para obter o número máximo de mensagens e o comprimento máximo de mensagens da fila de mensagens. Coloque-o no mq_maxmsg e mq_msgsize da estrutura de dados.

4. Enviando uma mensagem Após o
processo abrir a fila de mensagens, você pode usar a seguinte função para enviar uma mensagem

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

mqdes: O descritor obtido ao abrir a fila de mensagens.
ptr: Ponteiro para o buffer de envio, o buffer de envio armazena os dados a serem enviados.
Len: o comprimento dos dados a serem enviados.
prio: a prioridade da mensagem; é um número menor que MQ_PRIO_MAX, quanto maior o valor, maior a prioridade.
A fila de mensagens POSIX sempre retorna a mensagem mais antiga com a prioridade mais alta na fila quando mq_receive é chamado. Se a mensagem não precisar definir a prioridade, você pode definir prio como 0 em mq_send e definir prio em mq_receive como NULL. Valor de retorno: se o envio for bem-sucedido, retorna 0, se falhar, retorna -1.

5. Recebendo mensagens Depois que o
processo abre a fila de mensagens, você pode usar as seguintes funções para receber mensagens.

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

mqdes: O descritor obtido ao abrir a fila de mensagens.
ptr: Ponteiro para o buffer de recebimento. O buffer de recebimento é usado para armazenar as mensagens recebidas.
Len: o comprimento do buffer de recebimento. len não pode ser menor que mq_msgsize, caso contrário, retornará EMSGSIZE prio
: a prioridade da mensagem; é um número menor que MQ_PRIO_MAX, quanto maior o valor, maior a prioridade. A fila de mensagens POSIX sempre retorna a mensagem mais antiga com a prioridade mais alta na fila quando mq_receive é chamado. Se a mensagem não precisar definir a prioridade, você pode definir prio como 0 em mq_send e definir prio em mq_receive como NULL. Valor de retorno: Se o recebimento for bem-sucedido, retorna 0, se falhar, retorna -1.

6. A fila de mensagens está fechada

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

7, exclua a fila de mensagens

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

Quando um processo não fechou esta fila de mensagens, quando mq_unlink é chamado, a fila não será excluída imediatamente. Quando o último processo fechar a fila, a fila será excluída

Código

O exemplo cria dois novos projetos, inicia dois aplicativos, usa a fila de mensagens para se comunicar e o protótipo da função de interface é apresentado na nota:
projeto 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);
}

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

Mostrar resultados

Insira a descrição da imagem aqui

Arquivo de fila de mensagens

Depois que a fila de mensagens for criada, haverá um arquivo de fila de mensagens na pasta / dev / mqueue;
Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/weixin_40355471/article/details/113178838
Recomendado
Clasificación