Qt之进程间通信(共享内存)
一、简介
在Qt中,共享内存(Shared Memory)是一种进程间通信(Inter-Process Communication, IPC)机制,允许多个进程共享同一块内存区域。共享内存提供了高效的数据交换方式,适用于需要频繁传递大量数据的场景。
Qt中的共享内存机制主要依赖于QSharedMemory
类。该类提供了用于创建和管理共享内存区域的接口,允许进程在内存中创建一个共享的数据缓冲区。共享内存的原理如下:
-
创建共享内存: 使用
QSharedMemory
类的create()
函数可以创建一个共享内存对象,并指定一个唯一的键(key)来标识共享内存区域。如果该键对应的共享内存已经存在,则会返回false
。 -
分配内存: 一旦创建共享内存对象,可以使用
QSharedMemory
类的attach()
函数将共享内存附加到当前进程的地址空间。这样,进程就可以访问共享内存中的数据了。 -
写入和读取数据: 通过共享内存附加到的地址,进程可以直接读取或写入共享内存中的数据。可以使用任何数据结构,如数组、结构体等来组织共享的数据。
-
分离和删除共享内存: 当进程不再需要访问共享内存时,可以使用
QSharedMemory
类的detach()
函数将共享内存从当前进程的地址空间中分离。而使用QSharedMemory
类的remove()
函数可以删除共享内存区域,释放相关资源。
需要注意的是,共享内存并不提供进程同步和互斥的机制。在使用共享内存进行进程间通信时,需要采用其他的同步机制,如信号量、互斥锁等,来确保数据的正确读写。
二、QSharedMemory介绍
QSharedMemory在读写内存的时候,需要使用lock()来实现数据的同步,通过使用attach()访问共享内存,如果附加操作成功,则返回 true。 如果返回 false,则调用 error() 来确定发生了哪个错误。 附加共享内存段后,可以通过调用data()获得一个指向共享内存的指针。
QSharedMemory分为ReadOnly模式和ReadWrite模式;QSharedMemory::ReadOnly模式只能通过只读模式访问共享内存,而使用QSharedMemory::ReadWrite模式则可以通过读写模式访问共享内存。
QSharedMemory拥有进程并提供可以返回共享内存区域指针的成员函数。在共享内存区域,成员函数constData()可以通过void类型返回进程正在使用的内存区域指针。创建共享时,QSharedMemory可以以字节为单位分配共享内存区域,还可以通过第二个参数设置函数attach()提供的模式,使用函数setKey()可以设置与独立与平台的键。函数setKey()可以为共享内存创建唯一的标志key,通过这个key来查询到相对应的共享内存。
三、数据写入到共享内存中
#define SHARED_MEMORY_KEY "shared_memory" typedef struct { int status; int width; int height; char buffer[1024]; } MemoryInfo; class MainWindow : public QObject { Q_OBJECT public: explicit MainWindow(QObject *parent = nullptr); ~MainWindow(); private slots: void on_start_timer(); private: QSharedMemory *m_shared_memory; QTimer *m_start_timer; MemoryInfo *m_memory_data; int m_screen_width; int m_screen_height; };
MainWindow::MainWindow(QObject *parent) : QObject(parent) { m_screen_width = GetSystemMetrics(SM_CXSCREEN); m_screen_height = GetSystemMetrics(SM_CYSCREEN); m_memory_data = new MemoryInfo; m_shared_memory = new QSharedMemory; m_shared_memory->setKey(SHARED_MEMORY_KEY); if (!m_shared_memory->attach(QSharedMemory::ReadWrite)) { m_shared_memory->create(sizeof(MemoryInfo), QSharedMemory::ReadWrite); } m_start_timer = new QTimer(this); connect(m_start_timer, &QTimer::timeout, this, &MainWindow::on_start_timer); m_start_timer->start(5000); } MainWindow::~MainWindow() { delete m_memory_data; delete m_shared_memory; } void MainWindow::on_start_timer() { qDebug() << "start shared memory..."; const char *shared_info = "shared memory"; m_memory_data->status = 1; m_memory_data->width = m_screen_width; m_memory_data->height = m_screen_height; memcpy(m_memory_data->buffer, shared_info, strlen(shared_info)); m_shared_memory->lock(); memcpy(m_shared_memory->data(), m_memory_data, sizeof(MemoryInfo)); m_shared_memory->unlock(); }
四、从共享内存中读数据
#include <QThread> #include <QSharedMemory> #define SHARED_MEMORY_KEY "shared_memory" typedef struct { int status; int width; int height; char buffer[1024]; } MemoryInfo; class MainWindow : public QThread { Q_OBJECT public: explicit MainWindow(); ~MainWindow(); protected: void run() override; private: QSharedMemory *m_shared_memory; MemoryInfo *m_memory_info; };
MainWindow::MainWindow() { m_shared_memory = new QSharedMemory; m_shared_memory->setKey(SHARED_MEMORY_KEY); } MainWindow::~MainWindow() { delete m_shared_memory; } void MainWindow::run() { while (true) { if (!m_shared_memory->attach(QSharedMemory::ReadOnly)) { qDebug() << "waiting write_memory process start... "; QThread::sleep(5); } else { break; } } while (true) { m_shared_memory->lock(); m_memory_info = (MemoryInfo*)m_shared_memory->constData(); int status = m_memory_info->status; if (status == 1) { int width = m_memory_info->width; int height = m_memory_info->height; char buffer[1024] = {0}; memcpy(buffer, m_memory_info->buffer, sizeof (buffer) / sizeof (buffer[0])); qDebug() <<"---------------------start---------------------"; qDebug() << width << "*" << height; qDebug() << "status:" << status; qDebug() << "buffer:" << buffer; qDebug() <<"---------------------end-----------------------"; QThread::sleep(5); } m_shared_memory->unlock(); } }
五、效果展示
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· DeepSeek “源神”启动!「GitHub 热点速览」
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器