QT使用共享内存实现进程间通讯
更新时间:2024年12月13日 09:17:22 作者:hss2799
这篇文章主要为大家详细介绍了QT如何使用共享内存实现进程间通讯,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
QSharedMemory:如果两个进程运行在同一台机器上,且对性能要求非常高(如实时数据共享、图像渲染等),建议使用共享内存。
优点:
- 高性能: 共享内存是进程间通信的最快方式之一,因为数据直接在内存中共享,不需要经过内核的系统调用或网络协议栈。
- 低延迟: 由于数据直接在内存中传递,延迟非常低,适合需要高性能的场景(如实时数据处理、图像渲染等)。
- 简单数据共享: 适合两个进程需要频繁访问相同数据的场景。
设计思路
共享内存区:用于存储数据。
互斥量:用于保护共享内存区,防止多个进程同时访问导致数据不一致。
信号量:用于通知对方有数据可用。
服务器实现
头文件
#ifndef SHAREDMEMORYSERVICE_H #define SHAREDMEMORYSERVICE_H #include <QObject> #include <QSharedMemory> #include <QBuffer> #include <QDataStream> #include <QDebug> #include <QThread> #include <QSystemSemaphore> class SharedMemoryService : public QObject { Q_OBJECT public: explicit SharedMemoryService(QObject* parent = nullptr); ~SharedMemoryService(); // 向共享内存中写入数据 bool writeToSharedMemory(const QByteArray& data); signals: // 当读取到共享内存中的数据时发出信号 void signalRead(QBuffer& buffer); private slots: // 检查共享内存中的数据 void checkSharedMemory(); private: std::shared_ptr<QSharedMemory> m_sharedMemory; // 共享内存 std::shared_ptr<QSystemSemaphore> m_semaphoreClient; // 信号量 - 客户端发送 std::shared_ptr<QSystemSemaphore> m_semaphoreService; // 信号量- 服务器发送 bool m_bCreate = false; // 是否创建成功 bool m_bExit = false; // 是否退出 QThread m_listenThread; // 监听线程 }; #endif // SHAREDMEMORYSERVICE_H
cpp
#include "SharedMemoryService.h" SharedMemoryService::SharedMemoryService(QObject* parent) : QObject(parent), m_sharedMemory(std::make_shared<QSharedMemory>("MySharedMemoryKey_XXX")), m_semaphoreClient(std::make_shared<QSystemSemaphore>("MySemaphoreKey_XXX", 0)), m_semaphoreService(std::make_shared<QSystemSemaphore>("MySemaphoreKey_XXX2", 0)) { // 创建共享内存,大小为1024字节 if (!m_sharedMemory->create(1024)) { qDebug() << "无法创建共享内存:" << m_sharedMemory->errorString(); return; } m_bCreate = true; // 移动监听线程到单独的线程中 QObject::connect(&m_listenThread, &QThread::started, this, &SharedMemoryService::checkSharedMemory, Qt::DirectConnection); m_listenThread.start(); } SharedMemoryService::~SharedMemoryService() { m_bExit = true; m_semaphoreClient->release(1); // 停止监听线程 m_listenThread.quit(); m_listenThread.wait(); } void SharedMemoryService::checkSharedMemory() { if (!m_bCreate || !m_sharedMemory->isAttached()) return; while (true) { // 等待信号量 if (m_semaphoreClient->acquire()) { if (m_bExit) { break; } if (m_sharedMemory->lock()) { // 读取共享内存中的数据 QBuffer buffer; buffer.setData((char*)m_sharedMemory->data(), m_sharedMemory->size()); buffer.open(QIODevice::ReadOnly); // 如果共享内存中有数据,则发出信号 if (buffer.size() > 0) { emit signalRead(buffer); // 清空共享内存内容 memset(m_sharedMemory->data(), 0, m_sharedMemory->size()); } // 解锁共享内存 m_sharedMemory->unlock(); } } } } bool SharedMemoryService::writeToSharedMemory(const QByteArray& data) { if (!m_bCreate || !m_sharedMemory->isAttached()) { qDebug() << "共享内存未创建或未附加"; return false; } if (m_sharedMemory->lock()) { // 将数据写入共享内存 memcpy(m_sharedMemory->data(), data.data(), qMin(data.size(), m_sharedMemory->size())); // 释放锁 m_sharedMemory->unlock(); // 增加信号量计数,通知监听线程有数据可用 m_semaphoreService->release(1); return true; } qDebug() << "无法锁定共享内存"; return false; }
调用
/// 创建共享内存 void MainWindow::slotCrateBtn() { if (m_service) { return; } ui->btnCreate->setEnabled(false); m_service = new SharedMemoryService(); // 连接信号槽,监听共享内存中的数据 QObject::connect(m_service, &SharedMemoryService::signalRead, this, &MainWindow::slotRecv, Qt::DirectConnection); } /// 发送内容 void MainWindow::slotSendBtn() { if (m_service == nullptr) { return; } // 向共享内存中写入数据 QByteArray data = ui->textEditSend->toPlainText().toLocal8Bit(); if (m_service->writeToSharedMemory(data)) { qDebug() << "数据已成功写入共享内存"; } else { qDebug() << "写入共享内存失败"; } } /// 收到数据 void MainWindow::slotRecv(QBuffer& buffer) { QString text = buffer.data(); if (text.isEmpty()) { return; } qDebug() << "接收到共享内存中的数据:" << text; ui->textEdit->append(text); }
客户端实现
头文件
#ifndef SHAREDMEMORYCLIENT_H #define SHAREDMEMORYCLIENT_H #include <QObject> #include <QSharedMemory> #include <QBuffer> #include <QDataStream> #include <QDebug> #include <QThread> #include <QSystemSemaphore> #include <cstdio> #include <iostream> #include <list> #include <memory> #include <string> class SharedMemoryClient : public QObject { Q_OBJECT public: explicit SharedMemoryClient(QObject* parent = nullptr); ~SharedMemoryClient(); // 向共享内存中写入数据 bool writeToSharedMemory(const QByteArray& data); signals: // 当读取到共享内存中的数据时发出信号 void signalRead(QBuffer& buffer); private slots: // 处理共享内存中的数据 void processSharedMemory(); private: std::shared_ptr<QSharedMemory> m_sharedMemory; // 共享内存 std::shared_ptr<QSystemSemaphore> m_semaphoreClient; // 信号量 - 客户端发送 std::shared_ptr<QSystemSemaphore> m_semaphoreService; // 信号量- 服务器发送 bool m_bCreate = false; // 是否创建成功 bool m_bExit = false; // 是否退出 QThread m_listenThread; // 监听线程 }; #endif // SHAREDMEMORYCLIENT_H
cpp
#include "SharedMemoryClient.h" SharedMemoryClient::SharedMemoryClient(QObject* parent) : QObject(parent), m_sharedMemory(std::make_shared<QSharedMemory>("MySharedMemoryKey_XXX")), m_semaphoreClient(std::make_shared<QSystemSemaphore>("MySemaphoreKey_XXX", 0)), m_semaphoreService(std::make_shared<QSystemSemaphore>("MySemaphoreKey_XXX2", 0)) { if (!m_sharedMemory->attach()) { qDebug() << "无法附加到共享内存:" << m_sharedMemory->errorString(); return; } m_bCreate = true; // 将处理方法移动到监听线程中 moveToThread(&m_listenThread); connect(&m_listenThread, &QThread::started, this, &SharedMemoryClient::processSharedMemory, Qt::DirectConnection); // 启动监听线程 m_listenThread.start(); } SharedMemoryClient::~SharedMemoryClient() { m_bExit = true; m_semaphoreService->release(1); // 停止监听线程 m_listenThread.quit(); m_listenThread.wait(); } void SharedMemoryClient::processSharedMemory() { while (true) { if (m_semaphoreService->acquire()) { if (m_bExit) { break; } if (!m_bCreate || !m_sharedMemory->isAttached()) continue; // 锁定共享内存 if (m_sharedMemory->lock()) { // 检查共享内存是否有数据 QBuffer buffer; buffer.setData((char*)m_sharedMemory->data(), m_sharedMemory->size()); buffer.open(QIODevice::ReadOnly); // 如果共享内存中有数据,则发出信号 if (buffer.size() > 0) { emit signalRead(buffer); // 清空共享内存内容 memset(m_sharedMemory->data(), 0, m_sharedMemory->size()); } // 解锁共享内存 m_sharedMemory->unlock(); } } } } bool SharedMemoryClient::writeToSharedMemory(const QByteArray& data) { if (!m_bCreate || !m_sharedMemory->isAttached()) { qDebug() << "共享内存未创建或未附加"; return false; } // 锁定共享内存 if (m_sharedMemory->lock()) { // 将数据写入共享内存 memcpy(m_sharedMemory->data(), data.data(), qMin(data.size(), m_sharedMemory->size())); // 解锁共享内存 m_sharedMemory->unlock(); // 释放信号量,通知监听线程 m_semaphoreClient->release(1); return true; } qDebug() << "无法锁定共享内存"; return false; }
调用
/// 连接共享内存 void MainWindow::slotCrateBtn() { if (m_client) { return; } ui->btnCreate->setEnabled(false); m_client = new SharedMemoryClient(); // 连接信号槽,监听共享内存中的数据 QObject::connect(m_client, &SharedMemoryClient::signalRead, this, &MainWindow::slotRecv, Qt::DirectConnection); } /// 发送内容 void MainWindow::slotSendBtn() { if (m_client == nullptr) { return; } // 向共享内存中写入数据 QByteArray data = ui->textEditSend->toPlainText().toLocal8Bit(); if (m_client->writeToSharedMemory(data)) { qDebug() << "数据已成功写入共享内存"; } else { qDebug() << "写入共享内存失败"; } } /// 收到数据 void MainWindow::slotRecv(QBuffer& buffer) { QString text = buffer.data(); if (text.isEmpty()) { return; } qDebug() << "接收到共享内存中的数据:" << text; ui->textEdit->append(text); }
运行效果
以上就是QT使用共享内存实现进程间通讯的详细内容,更多关于QT进程间通讯的资料请关注脚本之家其它相关文章!
相关文章
C语言详细分析贪心策略中最小生成树的Prime算法设计与实现
最小生成树的问题还是比较热门的,最经典的莫过于Prime算法和Kruskal算法了,这篇博文我会详细讲解Prime算法的设计思想与具体代码的实现,不要求数据结构学的有多好,只要跟着我的思路来,一步一步的分析,调试,终能成就自己,那就让我们开始吧2022-05-05
最新评论