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
Arquivo de fila de mensagens
Depois que a fila de mensagens for criada, haverá um arquivo de fila de mensagens na pasta / dev / mqueue;