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);
}
运行效果:
原文地址:https://blog.csdn.net/hss2799/article/details/144430659
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!