Qt进程间通信之QSharedMemory示例

Posted 沧海一笑-dj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt进程间通信之QSharedMemory示例相关的知识,希望对你有一定的参考价值。

00. 目录

01. 概述

QSharedMemory提供了多个线程和进程对共享内存段的访问。它还提供了一种方法,让单个线程或进程锁定内存以进行独占访问。

当使用这个共享内存类时,请注意以下平台差异:

Windows:QSharedMemory 不“拥有”共享内存段。当所有具有连接到特定共享内存段的 QSharedMemory 实例的线程或进程已销毁其 QSharedMemory 实例或退出时,Windows 内核会自动释放共享内存段。

Unix:QSharedMemory“拥有”共享内存段。当将 QSharedMemory 实例附加到特定共享内存段的最后一个线程或进程通过销毁其 QSharedMemory 实例与该段分离时,Unix 内核会释放共享内存段。但是如果最后一个线程或进程在没有运行 QSharedMemory 析构函数的情况下崩溃,共享内存段会在崩溃中幸存下来。

HP-UX:每个进程只允许一个连接到共享内存段。这意味着 QSharedMemory 不应跨 HP-UX 中同一进程中的多个线程使用。

记得在对共享内存进行读写之前用lock ()锁住共享内存,完成后记得用unlock ()释放锁。

当 QSharedMemory 的最后一个实例与段分离时,QSharedMemory 会自动销毁共享内存段,并且不会保留对该段的引用。

02. 开发环境

Windows系统:Windows10

Qt版本:Qt5.15或者Qt6

03. 编程步骤

共享内存中数据提供方:

A、定义QSharedMemory shareMemory,并设置标志名shareMemory.setKey();
B、将共享内存与主进程分离 shareMemory.detach();
C、创建共享内存 shareMemory.create();
D、将共享内存上锁shareMemory.lock();
E、将进程中要共享的数据拷贝到共享内存中;
F、将共享内存解锁shareMemory.unlock();

共享内存中数据使用方:

A、定义QSharedMemory shareMemory,并设置与共享内存提供方一致的标志名shareMemory.setKey()。
B、将共享内存与主进程绑定shareMemory.attach(),使主进程可以访问共享内存的数据;
C、将共享内存上锁shareMemory.lock();
D、从共享内存中取数据;
E、使用完后将共享内存解锁shareMemory.unlock(),并将共享内存与进程分离shareMemory.detach();

04. 写端程序示例

widget.h文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include <QSharedMemory>


QT_BEGIN_NAMESPACE
namespace Ui  class Widget; 
QT_END_NAMESPACE

class Widget : public QWidget

    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;

    QSharedMemory *m_sharedMemory = nullptr;
;
#endif // WIDGET_H

widget.cpp文件

#include "widget.h"
#include "ui_widget.h"

#include <QDebug>
#include <QString>
#include <QFileDialog>
#include <QImage>
#include <QBuffer>
#include <QDataStream>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)

    ui->setupUi(this);

    //创建对象 设置Key
    m_sharedMemory = new QSharedMemory;
    m_sharedMemory->setKey("Kitty");



Widget::~Widget()

    delete ui;



//选择图片按钮槽函数
void Widget::on_pushButton_clicked()


    //如果指定Key共享内存已经关联,则解除关联
    if (m_sharedMemory->isAttached())
    
        if (!m_sharedMemory->detach())
        
            qDebug() << m_sharedMemory->errorString();
            return;
        
    


    //选择图片文件
    QString fileName = QFileDialog::getOpenFileName(this, "", "", "Images(*.*)");

    QImage image(fileName);
    ui->label->setPixmap(QPixmap::fromImage(image).scaled(256, 256));

    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    QDataStream out(&buffer);

    out << image;


    //创建共享内存
    if (!m_sharedMemory->create(buffer.size()))
    
        qDebug() << m_sharedMemory->errorString();
        return;
    

    //加锁
    m_sharedMemory->lock();

    char *data = (char *)m_sharedMemory->data();

    const char *from = buffer.data().data();
    memcpy(data, from, qMin(m_sharedMemory->size(), (int)buffer.size()));

    //解锁
    m_sharedMemory->unlock();


main.cpp文件

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();


执行结果如下:

05. 读端程序示例

widget.h文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include <QSharedMemory>



QT_BEGIN_NAMESPACE
namespace Ui  class Widget; 
QT_END_NAMESPACE

class Widget : public QWidget

    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QSharedMemory *m_sharedMemory = nullptr;

;
#endif // WIDGET_H

widget.cpp文件

#include "widget.h"
#include "ui_widget.h"

#include <QDebug>
#include <QBuffer>
#include <QDataStream>
#include <QImage>
#include <QPixmap>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)

    ui->setupUi(this);

    //m_sharedMemory = new QSharedMemory("Kitty");

    m_sharedMemory = new QSharedMemory;
    m_sharedMemory->setKey("Kitty");




Widget::~Widget()

    delete ui;



//读取共享内存槽函数
void Widget::on_pushButton_clicked()

    //关联共享内存
    if (m_sharedMemory->attach())
    
        qDebug() << "关联共享内存成功";
    
    else
    
        qDebug() << m_sharedMemory->errorString();
        return;
    

    QBuffer buffer;
    QDataStream in(&buffer);
    QImage image;

    //加锁
    m_sharedMemory->lock();


    buffer.setData((char*)m_sharedMemory->constData(), m_sharedMemory->size());
    buffer.open(QBuffer::ReadOnly);
    in >> image;

    //解锁
    m_sharedMemory->unlock();

    //共享内存解除关联
    if (!m_sharedMemory->detach())
    
        qDebug() << m_sharedMemory->errorString();
        return;
    

    ui->label->setPixmap(QPixmap::fromImage(image));


main.cpp文件

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();


执行结果如下

06. 附录

6.1 Qt教程汇总
网址:https://dengjin.blog.csdn.net/article/details/115174639

6.2 程序下载
下载:【Qt】进程间通信之QSharedMemory程序.rar

以上是关于Qt进程间通信之QSharedMemory示例的主要内容,如果未能解决你的问题,请参考以下文章

QtQt之进程间通信(共享内存)转

利用QSystemSemaphore和QSharedMemory实现进程间通讯

Qt基础之二十:进程间通信

Qt基础之二十:进程间通信

Qt基础之二十一:QtRO(Qt Remote Object)实现进程间通信

Qt基础之二十一:QtRO(Qt Remote Object)实现进程间通信