Qt::共享内存

Qt使用QSharedMemory类操作共享内存段。把QSharedMemory看做一种指针,这种指针指向分配出来的一个共享内存段,这个共享内存段是由底层操作系统提供,可以供多个线程或进程使用。QSharedMemory不“拥有”共享内存段,当某一线程销毁QSharedMemory实例,或者所有线程都退出,WinDOWS内核会自动释放共享内存段。

共享数据
  • 创建共享内存(指定内存区域大小和名字)
  • 锁定共享内存
  • 写入数据到共享内存
  • 结束锁定共享内存
获取数据
  • 连接共享内存(需要传入名字且与创建的内存区名字相同)
  • 锁定共享内存
  • 读取数据
  • 解除锁定共享内存
  • 断开连接
共享内存的实例如下:

首先是共享数据端:

#pragma once

#include <QtWidgets/QWidget>
#include <QTimer>
#include <QSharedMemory>
#include <QPixmap>
#include <QBuffer>
#include <QDataStream>
#include <QDebug>
#include <QFrame>
#include <QGridLayout>
#include <QPushButton>
#include <qmath.h>
#include "ui_ShareMemoryDemo1.h"

class ShareMemoryDemo1 : public QWidget
{
    Q_OBJECT

public:
    ShareMemoryDemo1(QWidget *parent = Q_NULLPTR);

private:
    Ui::ShareMemoryDemo1Class ui;
    const char* KEY_SHARED_MEMORY = "QSharedMemorydemo";
    QSharedMemory* WshareMerary = nullptr;
    QTimer* m_timer = nullptr;
    QWidget* m_ShareWiget = nullptr;
    QFrame* f = nullptr;

private:
    void createFrame();

private slots:
    void writeShareMeary();
};
#include "ShareMemoryDemo1.h"
#include <iostream>
#include <cstdint>
#include <stdint.h>

ShareMemoryDemo1::ShareMemoryDemo1(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    this->show();
    this->resize(600, 400);


    QFrame frame;
    f = new QFrame;
    createFrame();
    f->show();

    m_timer = new QTimer(this);
    QSharedMemory shareMerary(KEY_SHARED_MEMORY);
    //WshareMerary = &shareMerary;
    WshareMerary = new QSharedMemory(KEY_SHARED_MEMORY, this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(writeShareMeary()));
    if (!WshareMerary->create(600 * 400 * 4))
    {
        qDebug() << WshareMerary->errorString();
        return;
    }
    m_timer->start(100);
}

void ShareMemoryDemo1::writeShareMeary()
{
    QPixmap _image = f->grab();
    QBuffer buffer;
    QDataStream out(&buffer);
    buffer.open(QBuffer::ReadWrite);
    out << _image;
    int32_t size = buffer.size();
    WshareMerary->lock();
    uchar* to = static_cast<uchar*>(WshareMerary->data());
    const char* from = buffer.data().constData();
    if (to != nullptr && from != nullptr)
    {
        memcpy(to, &size, sizeof(int32_t));
        memcpy(to + sizeof(int32_t), from, qMin(size, WshareMerary->size()));
    }
    WshareMerary->unlock();
}

void ShareMemoryDemo1::createFrame()
{
    QGridLayout* layout = new QGridLayout;
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            layout->addWidget(new QPushButton(), i,j);
        }
    }
    f->setWindowFlags(Qt::WindowCloseButtonHint);
    f->setLayout(layout);
    f->resize(600, 400);
    f->show();
}

获取数据端:

#pragma once

#include <QtWidgets/QWidget>
#include <QTimer>
#include <QSharedMemory>
#include <QPixmap>
#include <QBuffer>
#include <QDataStream>
#include <QLabel>
#include <QDebug>
#include "ui_ShareMemoryDemo2.h"

class ShareMemoryDemo2 : public QWidget
{
    Q_OBJECT

public:
    ShareMemoryDemo2(QWidget *parent = Q_NULLPTR);


private:
    Ui::ShareMemoryDemo2Class ui;
	const char* KEY_SHARED_MEMORY = "QSharedMemorydemo";
	QSharedMemory* merary = nullptr;
	QTimer* m_timer = nullptr;
	QWidget* m_ShareWiget = nullptr;
	QLabel* RLabel = nullptr;

private slots:
	void readShareMerary();
};

#include "ShareMemoryDemo2.h"

ShareMemoryDemo2::ShareMemoryDemo2(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);

    
    m_timer = new QTimer();
    QSharedMemory RshareMemary(KEY_SHARED_MEMORY);
    RLabel = new QLabel();
    // merary = &RshareMemary;
    merary  = new QSharedMemory(KEY_SHARED_MEMORY, this);
    RLabel->resize(600, 400);
    RLabel->show();
    connect(m_timer, SIGNAL(timeout()), this, SLOT(readShareMerary()));
    m_timer->start(100);
}

void ShareMemoryDemo2::readShareMerary()
{
    if (!merary->attach())
    {
        qDebug() << "error" << merary->errorString();
    }
    QBuffer buffer;
    QDataStream in(&buffer);
    QPixmap pixmap;
    merary->lock();
    int32_t size = 0;
    const char* from = static_cast<const char*>(merary->constData());
    memcpy(&size, from, sizeof(int32_t));
    buffer.setData(from + sizeof(int32_t), size);
    buffer.open(QBuffer::ReadWrite);
    in >> pixmap;
    buffer.close();
    merary->unlock();
    merary->detach();
    RLabel->setPixmap(pixmap);
}

两个程序运行后效果如下:请添加图片描述

Qt中,线程间通讯可以使用共享内存来实现。共享内存是一种跨进程间共享数据的机制,可以在不同的线程间传递数据。 Qt提供了QSharedMemory类来操作共享内存。下面是一个使用共享内存进行线程间通讯的示例: ```cpp // 创建一个共享内存对象 QSharedMemory sharedMemory; // 设置共享内存的名称 sharedMemory.setKey("MySharedMemory"); // 在一个线程中写入数据到共享内存 if (sharedMemory.create(1024)) { sharedMemory.lock(); char* data = static_cast<char*>(sharedMemory.data()); // 在这里写入数据到共享内存 // 注意:要确保多个线程对共享内存的访问是互斥的,可以使用QMutex来实现互斥访问 sharedMemory.unlock(); } // 在另一个线程中读取共享内存中的数据 if (sharedMemory.attach()) { sharedMemory.lock(); char* data = static_cast<char*>(sharedMemory.data()); // 在这里读取共享内存中的数据 sharedMemory.unlock(); sharedMemory.detach(); } ``` 在上面的示例中,我们创建了一个名为"MySharedMemory"的共享内存对象,并设置了它的大小为1024字节。然后,在一个线程中写入数据到共享内存中,另一个线程则可以读取共享内存中的数据。 需要注意的是,在多个线程对共享内存进行读写时,需要确保访问的互斥性,以避免数据竞争。可以使用QMutex或其他同步机制来实现互斥访问。 另外,还可以使用信号与槽机制来实现线程间的通讯。Qt提供了QObject::moveToThread()方法,可以将一个QObject对象移动到指定的线程中,从而实现线程间的信号与槽的连接。这种方式相对于共享内存来说更加方便和安全。 希望以上信息能对你有帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值