Qt/C++进程间通信:QSharedMemory 使用详解(附演示Demo)
创作时间:
作者:
@小白创作中心
Qt/C++进程间通信:QSharedMemory 使用详解(附演示Demo)
引用
CSDN
1.
https://m.blog.csdn.net/chenai886/article/details/145145919
在开发跨进程应用程序时,进程间通信(IPC)是一个关键问题。Qt 框架提供了多种 IPC 技术,其中 QSharedMemory 是一种高效的共享内存方式,可以实现多个进程之间快速交换数据。本文将详细讲解 QSharedMemory 的概念、用法及其主要函数的用途,帮助开发者更好地理解和使用它。
1. 什么是 QSharedMemory?
QSharedMemory
是 Qt 中用于进程间共享内存的类。它允许多个进程共享一块内存区域,从而避免数据传输时的 IO 操作,提高通信速度。通过共享内存,多个进程可以直接读写这块内存,而无需经过文件或网络传递。
QSharedMemory 的核心特点
- 唯一键(Key)标识:
- 每块共享内存通过唯一的键(字符串)标识。
- 不同进程通过相同的键连接到共享内存。
- 线程安全性:
- 提供锁机制(
lock()
和unlock()
)以保护共享内存的读写。
- 跨平台支持:
- Qt 的跨平台特性使
QSharedMemory
可以在不同操作系统上无缝使用。
2. QSharedMemory 的常用场景
- 实时数据共享:
- 如传感器数据、实时日志等需要在多个进程间快速传递。
- 高性能需求:
- 在频繁更新的大量数据(如图像处理、缓存共享)中,通过共享内存减少通信开销。
- 进程间消息传递:
3. QSharedMemory 的工作流程
共享内存的基本使用可以分为以下几个步骤:
- 创建共享内存:
- 第一个进程通过
create(size)
创建一块共享内存。 - 分配的大小由数据的存储需求决定。
- 附加到共享内存:
- 其他进程通过
attach()
方法连接到已有的共享内存。
- 数据读写:
- 通过
lock()
和unlock()
保证线程安全,获取内存指针后读写数据。
- 释放共享内存:
4. QSharedMemory 常用函数详解
以下是 QSharedMemory
类的常用函数及其作用:
函数名 | 作用 |
---|---|
构造函数 | 创建 QSharedMemory 对象,指定唯一键标识共享内存。 |
create(size) | 创建指定大小的共享内存,如果共享内存已存在则返回失败。 |
attach() | 附加到已有的共享内存,连接成功后可以访问内存内容。 |
detach() | 断开与共享内存的连接,并释放资源(只有最后一个进程断开时共享内存才会被销毁)。 |
lock() | 锁定共享内存,防止其他进程或线程同时访问数据(用于数据同步)。 |
unlock() | 解锁共享内存,允许其他进程访问数据。 |
data() / constData() | 获取共享内存的指针,用于读写数据( data() 为可写指针,constData() 为只读指针)。 |
isAttached() | 检查当前进程是否已经连接到共享内存。 |
error() / errorString() | 获取最近一次操作的错误代码和描述,便于调试。 |
5. 使用示例:QSharedMemory 实现进程间通信
以下是一个完整的例子,展示如何通过 QSharedMemory
实现进程间的读写通信。
程序1:写入共享内存
程序1负责创建共享内存并向其中写入数据。
#include <QCoreApplication>
#include <QSharedMemory>
#include <QDebug>
#include <QTimer>
#include <QDateTime>
#define tc(a) QString::fromLocal8Bit(a)
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QSharedMemory sharedMemory("MySharedMemoryKey");
// 创建共享内存,大小为 1024 字节
if (!sharedMemory.create(1024)) {
qDebug() << tc("无法创建共享内存:") << sharedMemory.errorString();
return -1;
}
qDebug() << tc("共享内存已创建");
// 定时写入动态数据
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&]() {
if (sharedMemory.lock()) {
char *to = static_cast<char *>(sharedMemory.data());
QString message = tc("程序1动态消息#") + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
QByteArray byteArray = message.toLocal8Bit();
memcpy(to, byteArray.data(), byteArray.size() + 1); // 写入动态数据
sharedMemory.unlock();
qDebug() << tc("成功写入共享内存:") << message;
} else {
qDebug() << tc("无法锁定共享内存进行写入:") << sharedMemory.errorString();
}
});
timer.start(1000); // 每秒更新一次
return a.exec();
}
程序2:读取共享内存
程序2连接到共享内存,读取数据并解析时间戳。
#include <QCoreApplication>
#include <QSharedMemory>
#include <QDebug>
#include <QTimer>
#include <QDateTime>
#define tc(a) QString::fromLocal8Bit(a)
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QSharedMemory sharedMemory("MySharedMemoryKey");
// 连接到已有的共享内存
if (!sharedMemory.attach()) {
qDebug() << tc("无法连接到共享内存:") << sharedMemory.errorString();
return -1;
}
qDebug() << tc("成功连接到共享内存");
// 定时读取数据
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&]() {
if (sharedMemory.lock()) {
const char *from = static_cast<const char *>(sharedMemory.constData());
QString data = QString::fromLocal8Bit(from);
sharedMemory.unlock();
// 解析时间戳
QString timeStampString = data.split("#").at(1);
QDateTime messageTime = QDateTime::fromString(timeStampString, "yyyy-MM-dd hh:mm:ss.zzz");
// 当前时间
QDateTime currentTime = QDateTime::currentDateTime();
qDebug() << tc("从共享内存读取到的数据:") << data;
// 如果时间戳解析成功,计算时间差
if (messageTime.isValid()) {
qint64 timeDifference = messageTime.msecsTo(currentTime); // 时间差(毫秒)
qDebug() << tc("接收到的时间:") << messageTime.toString("yyyy-MM-dd hh:mm:ss.zzz");
qDebug() << tc("当前时间:") << currentTime.toString("yyyy-MM-dd hh:mm:ss.zzz");
qDebug() << tc("时间差(毫秒):") << timeDifference;
} else {
qDebug() << tc("无法解析时间戳!");
}
} else {
qDebug() << tc("无法锁定共享内存进行读取:") << sharedMemory.errorString();
}
});
timer.start(1000); // 每秒读取一次
return a.exec();
}
6. 注意事项
- 共享内存大小:
- 创建共享内存时,指定的大小必须足够大以存储所有数据。
- 锁机制:
- 在操作共享内存前,必须调用
lock()
进行锁定,以避免数据竞争。 - 使用完成后,必须调用
unlock()
解锁。
- 错误处理:
- 使用
error()
和errorString()
检查共享内存的状态。
- 进程退出:
7. 总结
QSharedMemory
是一种高效的进程间通信方式,适用于需要快速传递数据的场景。通过本文的讲解,您应该能够掌握 QSharedMemory
的核心功能及其应用。无论是共享日志、实时数据,还是跨进程消息传递,QSharedMemory
都是一个值得考虑的解决方案。
热门推荐
既真实又好看的10部高分年代剧,每部都是一代人的回忆
9部腾讯热播家庭剧推荐:梅婷主演两部,部部精彩不容错过
里脊肉在健康饮食中的角色探讨
感冒药和退烧药能一起吃吗?
Spearman 相关系数的可视化和应用场景
韩国银行卡使用全攻略:手续费、限额等关键信息详解
春季到底能不能吃参? 专家:遵循三大“黄金法则”
女孩山字旁最有涵养的字,山字头最旺女孩名字
装修必备工具全解析:墙面钻孔、扩缝、掏洞一应俱全
如何全面了解金融投资的风险和回报?这些风险和回报如何进行合理配置?
如何理解基金公司的运作模式?这些模式如何影响投资策略?
合理搭配,作物高产!有机肥与化肥这些搭配技巧,你掌握了吗?
胎压报警灯亮起的处理及消除方法
如何保证移动应用的可访问性
世界名著最动人的10句话,一生至少要读一次
住房租金怎么抵扣个税
隐形车衣想要贴全车,都包含哪些部位
跑步腰疼是什么原因?一文详解跑步腰疼的原因与治疗方法
丝瓜播种育苗方法
让故事更具生命力!揭秘如何用细节描写激发读者共鸣,创造真实感
舌头发红疼是怎么回事
为什么盐水能制冷
烧麦尽量少吃三样东西
减肥5天不拉屎?大便去哪了?专家解析原因与解决方案
白毫银针茶的品质与价格差异:如何选择性价比更高的茶叶?
物以“硒”为贵,但缺硒和盲补都不靠谱
厨房小贴士:三招有效避免隔夜菜危害健康!
零食很忙与赵一鸣合并案尘埃落定 市场监管总局:不具有排除、限制竞争的效果
CVA协会发布《数据资产估值指南》,规范数据资产估值行为
阜宁大糕的做法与配方:盐城特产玉带糕的制作工艺详解