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
暂无评论内容