- A+
所属分类:Qt专栏
介绍
共享内存指:多个进程/线程访问同一段内存或文件。
共享的内存需要明确两点:内存的位置、内存的大小。
QSharedMemory针对多线程/进程间实现共享内存的访问。针对单线程/进程提供锁定内存以实现独占的办法。
Qt在不同系统上的共享内存区分
- Windos的共享内存在所有引用的进程的关闭时(包括闪退)自动清空。
- Linux的共享内存在所有引用的进程的关闭时(不包括闪退)自动清空。
跨进程共享数据流程
共享内存中数据提供方:
A、定义QSharedMemory shareMemory,并设置标志名shareMemory.setKey();
B、将共享内存与当前进程分离 shareMemory.detach();
C、创建共享内存 shareMemory.create(),并attach;
D、将共享内存上锁shareMemory.lock();
E、将进程中要共享的数据拷贝到共享内存中;
F、将共享内存解锁shareMemory.unlock();
共享内存中数据使用方:
A、定义QSharedMemory shareMemory,并设置与共享内存提供方一致的标志名shareMemory.setKey()。
B、将共享内存与当前进程绑定shareMemory.attach(),使当前进程可以访问共享内存的数据;
C、将共享内存上锁shareMemory.lock();
D、从共享内存中取数据;
E、使用完后将共享内存解锁shareMemory.unlock(),并将共享内存与进程分离shareMemory.detach();
数据提供方进程
widget.h文件
- #ifndef WIDGET_H
- #define WIDGET_H
- #include <QWidget>
- #include <QSharedMemory>
- namespace Ui {
- class Widget;
- }
- class Widget : public QWidget
- {
- Q_OBJECT
- public:
- explicit Widget(QWidget *parent = nullptr);
- ~Widget();
- private:
- Ui::Widget *ui;
- QSharedMemory sharememory;
- private slots:
- void WriteShareMemory();
- };
- #endif // WIDGET_H
widget.cpp文件
- #include "widget.h"
- #include "ui_widget.h"
- #include <QBuffer>
- #include <QDataStream>
- #include <QDebug>
- Widget::Widget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::Widget)
- {
- ui->setupUi(this);
- sharememory.setKey("share");
- this->WriteShareMemory();
- }
- Widget::~Widget()
- {
- delete ui;
- }
- void Widget::WriteShareMemory()
- {
- //isAttached():该函数用来判断程序(调用该函数的程序)是否和共享内存进行关联,
- //是返回true,否返回false。
- if(sharememory.isAttached())
- {
- //detach():解除共享内存和程序的关联,即调用该函数后,程序不可以再访问共享内存。
- //如果该共享内存被多个程序实例所关联,当最后一个程序实例和共享内存解除关联后,
- //该共享内存将由操作系统自动释放掉。分离操作成功,返回true。如果返回false,
- //通常意味着该共享内存和程序分离失败,或者其他程序当前正在访问该共享内存,分离操作执行失败。
- sharememory.detach();
- }
- QBuffer buffer;
- buffer.open(QBuffer::ReadWrite);
- buffer.write("hello QT!");
- int size = buffer.size();
- if(!sharememory.create(size))//注意,create会自动attach进程。
- {
- qDebug() << sharememory.errorString();
- return ;
- }
- sharememory.lock();
- //data():程序关联共享内存的前提下,调用该函数返回共享内存中数据的起始地址。如果没有关联共享内存,则返回0。
- char *dest = reinterpret_cast<char *>(sharememory.data());
- const char *source = reinterpret_cast<const char *>(buffer.data().data());
- //size():调用该函数将返回程序所关联的共享内存的大小(字节)。如果没有关联的共享内存,则返回0。
- memcpy(dest, source, qMin(size, sharememory.size()));
- sharememory.unlock();
- }
main.cpp
- #include "mainwindow.h"
- #include <QApplication>
- #include "Widget.h"
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- Widget w;
- w.show();
- return a.exec();
- }
数据使用方进程
widget.h文件
- #ifndef WIDGET_H
- #define WIDGET_H
- #include <QWidget>
- #include <QSharedMemory>
- class Widget : public QWidget
- {
- Q_OBJECT
- public:
- explicit Widget(QWidget *parent = nullptr);
- private:
- QSharedMemory sharememory;
- private slots:
- void ReadShareMemory();
- };
- #endif // WIDGET_H
widget.cpp文件
- #include "widget.h"
- #include <QBuffer>
- #include <QDebug>
- Widget::Widget(QWidget *parent)
- : QWidget{parent}
- {
- //setKey ()函数用来为共享内存段设定关键字(为共享内存命名),
- //如果参数key的值和构造函数或者之前指定的关键字相同的话,则该函数将不做任何操作,直接返回。
- sharememory.setKey("share");
- this->ReadShareMemory();
- }
- void Widget::ReadShareMemory()
- {
- //将以关键字key命名的共享内存和当前程序进行关联
- //共享内存默认的访问方式为可读可写。
- //如果程序和共享内存关联成功,返回true,否则返回false。
- if(!sharememory.attach())
- {
- qDebug() << "cann't attach sahrememory!";
- }
- QBuffer buffer;
- //lock():如果共享内存资源当前处于释放状态,进程调用该函数将共享内存中的资源锁定,并返回true。其他进程将不能访问该共享内存。
- //如果共享内存被其他进程占用时,则该函数会一直处于阻塞状态,直到其他进程使用完毕,释放共享内存资源。
- sharememory.lock();
- buffer.setData((char*)sharememory.constData(),sharememory.size());
- buffer.open(QBuffer::ReadWrite);
- buffer.readAll();
- //unlock():如果共享内存资源被当前进程所占有,调用该函数将解锁该共享资源,并返回true。
- //如果当前进程没有占用该资源,或者共享内存被其他进程访问,则不做任何操作并返回false。
- sharememory.unlock();
- sharememory.detach();
- qDebug() << buffer.data().data();
- }
main.cpp文件
- #include "mainwindow.h"
- #include <QApplication>
- #include "Widget.h"
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- Widget w;
- w.show();
- return a.exec();
- }