QT ShareMemory共享内存

共享内存(Shared Memory)是一种最为高效的进程间通信方式,进程之间可以通过共享内存进行数据通信。共享内存是一个特定的内存区域,可以被多个进程同时访问。一个进程可以将数据写入共享内存,而另一个进程可以从共享内存读取数据。大数量数据的时候使用。

本实例使用QT实现了一个进程向共享内存写数据,一个进程向共享内存读数据。

照片存放位置在Debug的Image 里

(一)ShareMemory_write向共享内存中写入照片并展示在UI界面的Label中。

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_Btn_in_clicked();


private:
    Ui::Widget *ui;
    QSharedMemory *sharememory_write=nullptr;
};
#endif // WIDGET_H

widget.cpp源文件

#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QDebug>
#include <QBuffer>
#include <QDataStream>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    sharememory_write = new QSharedMemory("kis");
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_Btn_in_clicked()
{
    if(sharememory_write->isAttached())//判断程序是否关联共享内存
        sharememory_write->detach();//解除关联

    QString fileName = QFileDialog::getOpenFileName(this,"打开文件",QString(),tr("Image(*.jpg *.gif *.png)"));
    QImage image;
    if(!image.load(fileName)){
        qDebug()<<"加载图片失败";
        return;
    }
    ui->label->setPixmap(QPixmap::fromImage(image).scaled(ui->label->width(),ui->label->height()));

    QByteArray pixArray;
    QBuffer buffer(&pixArray);
    buffer.open(QIODevice::ReadWrite);//pixmap不能为空,必须先将图片加载到pixmap中
    image.save(&buffer,"png");

//    qDebug()<<pixArray.size();
    //创建共享内存段,失败则显示错误原因
    if(!sharememory_write->create(pixArray.size()))
    {
        qDebug()<<"创建共享内存失败";
        return;
    }

    sharememory_write->lock();
    memcpy(sharememory_write->data(),pixArray.data(),pixArray.size());//将图片存入共享内存中
    sharememory_write->unlock();

}




image.save(&buffer,"png");//注意一定要保留图片的原格式,不然我之前选的bmp格式,导出后图片背景为黑色,不是原图。

(二)ShareMemory_read读共享内存中的

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_Btn_out_clicked();

private:
    Ui::Widget *ui;
    QSharedMemory *sharememory_read=nullptr;
};
#endif // WIDGET_H

照片并展示在UI界面的Label中。

widget.cpp源文件

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    sharememory_read = new QSharedMemory("kis");
    sharememory_read->attach();//将共享内存附加到当前进程的地址空间
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_Btn_out_clicked()
{
    //尝试将该进程附加到共享内存段,成功返回true
    if(!sharememory_read->isAttached())//判断程序是否关联共享内存
    {
        qDebug()<<"无法关联共享内存";
        return;
    }

    QByteArray array;
    array.resize(sharememory_read->size());
    sharememory_read->lock();
    //方法一将图片存入共享内存中
//    memcpy(array.data(),(char *)sharememory_read->constData(),sharememory_read->size());
   //方法二
    memcpy(array.data(),sharememory_read->data(),sharememory_read->size());
    sharememory_read->unlock();

//    qDebug()<< QImage::fromData(array)<<sharememory_read->size()<<array.toHex('|');
    ui->label->setPixmap(QPixmap::fromImage(QImage::fromData(array)).scaled(ui->label->width(),ui->label->height()));
    sharememory_read->detach();
}

效果图如下:

我还存在疑问: 

步骤上,我必须先执行ShareMemory_write,将图片导入界面了才能再运行ShareMemory_read,如果两个程序先后启动,我再点导入按钮,导入图片后,点导出没有反应。导出图片后,关闭程序ShareMemory_write,执行ShareMemory_read,打印“关联共享内存失败”。

回答:当绑定共享内存的进程都被关闭,操作系统会回收这个共享内存空间。

当一个进程写入共享内存后,关闭这个程序,共享内存的数据不在了吗?为什么另一个进程用Key来调共享内存的数据会失败,必须两个进程都打开?

回答:共享内存在ShareMemory_write的on_Btn_in_clicked()函数里被创建,当没有点击按钮前,ShareMemory_read的构建函数里不能绑定共享内存。会报“关联共享内存失败”。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值