Qt进程通信之共享内存(QSharedMemory)

82 篇文章 1 订阅

首先介绍下什么是共享内存。
定义:
共享内存指 (shared memory)在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据。共享内存是 Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。
应用场景:
1、进程间通信。
两个进程同时挂载一片共享内存,进程A写、进程B读,就达到了通信效果,这种方案的好处是,读写都是基于内存操作,效率非常之高。
2、数据共享。
类似于读写锁中的读锁原理。这里是一个进程写了后,其它多个相同的进程进行读取这片数据。比如A进程写数据到共享内存,B、C进程从共享内存读取这片数据。
3、单进程数据缓存。
比如单机上只有一个实例,该实例需要在启动的时候加载一大块资源到内存,那么,如果基于共享内存,将资源加载到共享内存,那么,下次启动的时候,只要version或者crc没变,就可以直接挂载使用,无需再次读入。比如程序启动需要加载cpu型号、内存信息、系统属性、配置文件数据等等时,软件第一次启动时先将数据加载到共享内存,后面启动时只需要从共享内存读取数据,提升程序的启动速度。
4、保证软件不重复启动。
通过共享内存绑定程序,再次启动这个程序时,进行判断该共享内存是否被绑定,是否还能够再次创建成功,来防止软件重复启动。

这里只展示场景1、2、4的代码示例。
场景1和场景2:
进程A写共享内存。

        m_shareMemory.setKey("shared momery");
        if(m_shareMemory.isAttached())
             m_shareMemory.detach();//将该进程与共享内存段分离
        QBuffer buffer;     //创建缓冲区绑定数据流,然后通过数据流写数据,这样能保证数据的格协议式和编码格式不被干扰。
        QDataStream in(&buffer);
        buffer.open(QBuffer::ReadWrite);
        in<<“test data”;
        int size = buffer.size();
        if(!m_shareMemory.create(size))
        {
            qDebug()<<"can't create memory segment"<<m_shareMemory.error();
        }
        m_shareMemory.lock();
        char *to = (char*)m_shareMemory.data();
        const char *from = (char*)buffer.data().data();
        memcpy(to,from,qMin(size,m_shareMemory.size()));//数据从该进程中拷贝到共享数据内存中
        m_shareMemory.unlock();//共享内层解锁
        m_shareMemory.detach();
    }

进程B读共享内存

    m_shareMemory.setKey("shared momery");
    if(!m_shareMemory.attach())//将shareMemory与该进程绑定使之可以访问shareMemory里的内容
    {
        qDebug()<<tr("can't attach share memory");
        m_shareMemory.detach();//将shareMemeory与该进程分离
    }
    if (m_shareMemory.isAttached())
    {
        QByteArray data;
        QBuffer buffer;  /创建缓冲区绑定数据流,同样通过数据流读数据。这里buffer可以不通过数据流拿数据,但是这样会造成数据的格式变化。
        QDataStream out(&buffer);
        m_shareMemory.lock();//给shareMemory加锁
        buffer.setData((char*)m_shareMemory.constData(),m_shareMemory.size());//将shareMemeory里的数据放到buffer里
        buffer.open(QBuffer::ReadWrite);
        out>>data;
        qDebug()<<data;
        m_shareMemory.unlock();//将shareMemory解锁
        m_shareMemory.detach();
    }

进程C读数据

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

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    startTimer(1000);
    m_shareMemory.setKey("shared momery");
    if (!m_shareMemory.attach())
    {
        qDebug()<<"attach is failed ";
        m_shareMemory.detach();
    }
}

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

void Widget::timerEvent(QTimerEvent *event)
{
    QByteArray array;
    QBuffer buffer;
    QDataStream out(&buffer);
    m_shareMemory.lock();
    buffer.setData((char*)m_shareMemory.constData(),m_shareMemory.size());
    buffer.open(QBuffer::ReadWrite);
    out>>array;
    qDebug()<<array;
    m_shareMemory.unlock();
}

场景4:代码介绍

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Qt 中,可以使用 QSharedMemory 类实现共享内存,进程间通信的过程包括以下步骤: 1. 创建共享内存区域:在某个进程中创建一个 QSharedMemory 对象,调用 create() 函数创建共享内存区域,指定共享内存的大小和其他属性。 2. 连接共享内存区域:在其他进程中也创建一个 QSharedMemory 对象,调用 attach() 函数连接到已经创建的共享内存区域,获取共享内存的地址。多个进程可以通过同一个 key 值连接到同一块共享内存区域。 3. 在共享内存中进行数据交换:多个进程都可以访问共享内存区域中的数据,可以使用锁机制等方式来确保数据的同步和正确性。在 Qt 中,可以使用 QMutex 等类来实现锁机制。 4. 调用函数:在共享内存中存储的数据通常是一些结构体、类或对象等,可以在一个进程中修改这些数据,然后在另一个进程中调用相应的函数来处理这些数据。在 Qt 中,可以使用 QBuffer、QDataStream 等类来实现数据的序列化和反序列化,以便在进程间传递数据。 5. 断开共享内存连接:当不再需要访问共享内存区域时,需要调用 detach() 函数断开与共享内存的连接。 6. 删除共享内存区域:当所有进程都不再使用共享内存区域时,需要调用 QSharedMemory 的 static remove() 函数删除共享内存区域,释放资源。 需要注意的是,在使用共享内存进行进程间通信时,需要考虑数据同步和互斥等问题,以避免数据竞争和死锁等情况。同时,由于共享内存是操作系统资源,应该在使用完毕后及时释放,避免内存泄漏和资源浪费。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方忘忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值