QSharedMemory跨进程通信例子 Qt系列教程

  • A+
所属分类:Qt专栏 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文件

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QSharedMemory>
  5. namespace Ui {
  6. class Widget;
  7. }
  8. class Widget : public QWidget
  9. {
  10.     Q_OBJECT
  11. public:
  12.     explicit Widget(QWidget *parent = nullptr);
  13.     ~Widget();
  14. private:
  15.     Ui::Widget *ui;
  16.     QSharedMemory sharememory;
  17. private slots:
  18.     void WriteShareMemory();
  19. };
  20. #endif // WIDGET_H

 

widget.cpp文件

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. #include <QBuffer>
  4. #include <QDataStream>
  5. #include <QDebug>
  6. Widget::Widget(QWidget *parent) :
  7.     QWidget(parent),
  8.     ui(new Ui::Widget)
  9. {
  10.     ui->setupUi(this);
  11.     sharememory.setKey("share");
  12.     this->WriteShareMemory();
  13. }
  14. Widget::~Widget()
  15. {
  16.     delete ui;
  17. }
  18. void Widget::WriteShareMemory()
  19. {
  20.     //isAttached():该函数用来判断程序(调用该函数的程序)是否和共享内存进行关联,
  21.     //是返回true,否返回false。
  22.     if(sharememory.isAttached())
  23.     {
  24.         //detach():解除共享内存和程序的关联,即调用该函数后,程序不可以再访问共享内存。
  25.         //如果该共享内存被多个程序实例所关联,当最后一个程序实例和共享内存解除关联后,
  26.         //该共享内存将由操作系统自动释放掉。分离操作成功,返回true。如果返回false,
  27.         //通常意味着该共享内存和程序分离失败,或者其他程序当前正在访问该共享内存,分离操作执行失败。
  28.         sharememory.detach();
  29.     }
  30.     QBuffer buffer;
  31.     buffer.open(QBuffer::ReadWrite);
  32.     buffer.write("hello QT!");
  33.     int size = buffer.size();
  34.     if(!sharememory.create(size))//注意,create会自动attach进程。
  35.     {
  36.         qDebug() << sharememory.errorString();
  37.         return ;
  38.     }
  39.     sharememory.lock();
  40.     //data():程序关联共享内存的前提下,调用该函数返回共享内存中数据的起始地址。如果没有关联共享内存,则返回0。
  41.     char *dest = reinterpret_cast<char *>(sharememory.data());
  42.     const char *source = reinterpret_cast<const char *>(buffer.data().data());
  43.     //size():调用该函数将返回程序所关联的共享内存的大小(字节)。如果没有关联的共享内存,则返回0。
  44.     memcpy(dest, source, qMin(size, sharememory.size()));
  45.     sharememory.unlock();
  46. }

 

main.cpp

  1. #include "mainwindow.h"
  2. #include <QApplication>
  3. #include "Widget.h"
  4. int main(int argc, char *argv[])
  5. {
  6.     QApplication a(argc, argv);
  7.     Widget w;
  8.     w.show();
  9.     return a.exec();
  10. }

 

数据使用方进程

widget.h文件

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QSharedMemory>
  5. class Widget : public QWidget
  6. {
  7.     Q_OBJECT
  8. public:
  9.     explicit Widget(QWidget *parent = nullptr);
  10. private:
  11.     QSharedMemory sharememory;
  12. private slots:
  13.     void ReadShareMemory();
  14. };
  15. #endif // WIDGET_H

 

widget.cpp文件

  1. #include "widget.h"
  2. #include <QBuffer>
  3. #include <QDebug>
  4. Widget::Widget(QWidget *parent)
  5.     : QWidget{parent}
  6. {
  7.     //setKey ()函数用来为共享内存段设定关键字(为共享内存命名),
  8.     //如果参数key的值和构造函数或者之前指定的关键字相同的话,则该函数将不做任何操作,直接返回。
  9.     sharememory.setKey("share");
  10.     this->ReadShareMemory();
  11. }
  12. void Widget::ReadShareMemory()
  13. {
  14.     //将以关键字key命名的共享内存和当前程序进行关联
  15.     //共享内存默认的访问方式为可读可写。
  16.     //如果程序和共享内存关联成功,返回true,否则返回false。
  17.     if(!sharememory.attach())
  18.     {
  19.         qDebug() << "cann't attach sahrememory!";
  20.     }
  21.     QBuffer buffer;
  22.     //lock():如果共享内存资源当前处于释放状态,进程调用该函数将共享内存中的资源锁定,并返回true。其他进程将不能访问该共享内存。
  23.     //如果共享内存被其他进程占用时,则该函数会一直处于阻塞状态,直到其他进程使用完毕,释放共享内存资源。
  24.     sharememory.lock();
  25.     buffer.setData((char*)sharememory.constData(),sharememory.size());
  26.     buffer.open(QBuffer::ReadWrite);
  27.     buffer.readAll();
  28.     //unlock():如果共享内存资源被当前进程所占有,调用该函数将解锁该共享资源,并返回true。
  29.     //如果当前进程没有占用该资源,或者共享内存被其他进程访问,则不做任何操作并返回false。
  30.     sharememory.unlock();
  31.     sharememory.detach();
  32.     qDebug() << buffer.data().data();
  33. }

 

main.cpp文件

  1. #include "mainwindow.h"
  2. #include <QApplication>
  3. #include "Widget.h"
  4. int main(int argc, char *argv[])
  5. {
  6.     QApplication a(argc, argv);
  7.     Widget w;
  8.     w.show();
  9.     return a.exec();
  10. }

 

 

 

Qt大课堂-QtShare

发表评论

您必须登录才能发表评论!