Qt进程间通信:QSharedMemory 使用详解

1. 什么是 QSharedMemory?

QSharedMemory 是 Qt 中用于进程间共享内存的类。它允许多个进程共享一块内存区域,从而避免数据传输时的 IO 操作,提高通信速度。通过共享内存,多个进程可以直接读写这块内存,而无需经过文件或网络传递。

QSharedMemory 的核心特点

  1. 唯一键(Key)标识

    • 每块共享内存通过唯一的键(字符串)标识。

    • 不同进程通过相同的键连接到共享内存。

  2. 线程安全性

    • 提供锁机制(lock() 和 unlock())以保护共享内存的读写。

  3. 跨平台支持

    • Qt 的跨平台特性使 QSharedMemory 可以在不同操作系统上无缝使用。


2. QSharedMemory 的常用场景

  1. 实时数据共享

    • 如传感器数据、实时日志等需要在多个进程间快速传递。

  2. 高性能需求

    • 在频繁更新的大量数据(如图像处理、缓存共享)中,通过共享内存减少通信开销。

  3. 进程间消息传递

    • 两个或多个应用程序之间的简单数据交换。


3. QSharedMemory 的工作流程

共享内存的基本使用可以分为以下几个步骤:

  1. 创建共享内存

    • 第一个进程通过 create(size) 创建一块共享内存。

    • 分配的大小由数据的存储需求决定。

  2. 附加到共享内存

    • 其他进程通过 attach() 方法连接到已有的共享内存。

  3. 数据读写

    • 通过 lock() 和 unlock() 保证线程安全,获取内存指针后读写数据。

  4. 释放共享内存

    • 调用 detach() 断开与共享内存的连接。


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()) {constchar *from = static_cast<constchar *>(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. 注意事项

  1. 共享内存大小

    • 创建共享内存时,指定的大小必须足够大以存储所有数据。

  2. 锁机制

    • 在操作共享内存前,必须调用 lock() 进行锁定,以避免数据竞争。

    • 使用完成后,必须调用 unlock() 解锁。

  3. 错误处理

    • 使用 error() 和 errorString() 检查共享内存的状态。

  4. 进程退出

    • 调用 detach() 确保释放共享内存资源。


7. 总结

QSharedMemory 是一种高效的进程间通信方式,适用于需要快速传递数据的场景。通过本文的讲解,您应该能够掌握 QSharedMemory 的核心功能及其应用。无论是共享日志、实时数据,还是跨进程消息传递,QSharedMemory 都是一个值得考虑的解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/899023.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年3月全国计算机等级考试真题(二级C语言)

&#x1f600; 第1题 下列叙述中正确的是 A. 矩阵是非线性结构 B. 数组是长度固定的线性表 C. 对线性表只能作插入与删除运算 D. 线性表中各元素的数据类型可以不同 题目解析&#xff1a; A. 矩阵是非线性结构 错误。矩阵通常是二维数组&#xff0c;属…

基于Ebay拍卖网站成交价格的影响因素分析

摘要:近些年来网上拍卖的不断地发展&#xff0c;网上购物慢慢变成了大家普遍接受的购物方式。因此关于网上拍卖的研究日益成为很多人研究的重点。 影响拍卖网站价格的因素很多&#xff0c;但很少有人分得清楚哪些因素才是比较重要的因素&#xff0c;因此对价格因素分析&#x…

Langchain中的表格解析:RAG 和表格的爱恨情仇

实现 RAG(Retrieval-Augmented Generation)是一个挑战,尤其是在有效解析和理解非结构化文档中的表格时。这在处理扫描文档或图像格式的文档时尤为困难。这些挑战至少包括以下三个方面: 1.表格的“叛逆期”:不准确的解析可能会破坏表格结构: 表格在文档里就像个叛逆的青少…

Solr-搜索引擎-入门到精通

以下是对 Apache Solr 的简介及其常用语法的快速入门指南&#xff1a; 一、Solr 是什么&#xff1f; • 核心定位&#xff1a;Apache Solr 是一个基于 Lucene 的高性能、开源的搜索平台&#xff0c;支持全文检索、分词、高亮、聚合统计等功能。 • 核心功能&#xff1a; • 全…

原生后台GPS位置限制,降低功耗

1.后台 GPS 位置限制的背景 为了控制功耗&#xff0c;Android 平台对后台应用获取位置信息的频率进行了限制。后台的定义与后台执行限制一致&#xff0c;即应用不在前台运行时被视为后台应用。 2.更新间隔限制&#xff1a; 后台应用获取位置信息的更新间隔不能超过一定阈值。…

Docker 搭建 PlantUML 服务:高效生成 UML 图的最佳实践

PlantUML 是一款开源的 UML 图形生成工具&#xff0c;它支持生成类图、时序图、用例图、活动图等多种类型的 UML 图&#xff0c;广泛应用于软件设计、文档编写以及团队沟通中。通过 Docker 安装 PlantUML&#xff0c;开发者可以快速搭建环境&#xff0c;轻松生成 UML 图&#x…

简鹿办公汇总快速打开 Windows 资源管理器的几种方式

无论你是刚开始使用电脑的新手&#xff0c;还是已经有一定经验的用户&#xff0c;了解如何在 Windows 系统中打开资源管理器都是一个非常基本且重要的技能。Windows 资源管理器&#xff08;现在称为“文件资源管理器”&#xff09;是帮助你浏览、查找和管理计算机上所有文件的主…

嵌入式 python 安装

下载嵌入式Python后解压 https://www.python.org/ftp/python/3.12.9/python-3.12.9-embed-amd64.zip cd python-3.12.9-embed-amd64 安装 pip .\python.exe .\get-pip.py 放开限制 嵌入式 Python 为了减少体积&#xff0c;默认会有一些限制。你需要编辑 python312._pth 文…

DeepSeek底层揭秘——GEMM

目录 1. 什么是 GEMM&#xff1f; (1) 定义 (2) 核心目标 2. 核心功能 3. 对比传统通用矩阵乘法库 4. 技术要素 (1) 硬件感知优化 (2) 自动调优 (3) 高效内存管理 (4) 混合精度计算 5. 难点挑战&#xff08;含解决方案&#xff09; 6. 技术路径 7. 具体技术实现 8…

DNA-PAINT

参考: 【科研教程】NUPACK网页版使用教程 https://www.bilibili.com/video/BV1G94y1W7mN/NUPACK新版网页版教程-模拟部分 https://zhuanlan.zhihu.com/p/678730568NUPACK 4.0 User Guide https://docs.nupack.org/NUPACK网页版使用指南 https://zhuanlan.zhihu.com/p/55024017…

小程序内表格合并功能实现—行合并

功能介绍&#xff1a;支付宝小程序手写表格实现行内合并&#xff0c;依据动态数据自动计算每次需求合并的值&#xff0c;本次记录行内合并&#xff0c;如果列内合并&#xff0c;同理即可实现 前端技术&#xff1a;grid布局 display&#xff1a;grid 先看实现效果: axml&…

计算机视觉cv2入门之角点检测

角点是指图像中两条边缘线的交点&#xff0c;这些交点通常代表了图像中的重要特征。在计算机视觉中&#xff0c;角点检测是一种关键的技术&#xff0c;它可以帮助我们从图像中提取出这些重要的特征点&#xff0c;进而用于图像匹配、物体识别、图像拼接等多种应用。 角点检测示例…

抽奖的诱惑系统注册与登录功能测试报告

目录 一&#xff1a;项目背景 二&#xff1a;项目功能 &#xff08;1&#xff09; 注册功能 &#xff08;2&#xff09; 登录功能 电话 密码登录 电话 短信登录 三&#xff1a;设计测试用例 四&#xff1a;功能测试 五&#xff1a;自动化测试代码 七&#xff1a;遗留风…

【多媒体交互】Unity Kinect实现UI控件的点击

在Unity中&#xff0c;通过Kinect实现UI控件的点击功能&#xff0c;主要涉及手部追踪、坐标映射和手势检测三个核心环节。 实现步骤 初始化Kinect与关节追踪 使用KinectManager获取用户ID和手部关节点&#xff08;如JointType.HandLeft&#xff09;的坐标。 long userId _…

【蓝桥杯】每日练习 Day12 贡献法

前言 今天给大家带来两道贡献法的问题&#xff0c;先来讲一下什么是贡献法。 贡献法&#xff0c;与其说是一种算法&#xff0c;不如说是一种数学方法&#xff0c;是一种思维方式。 先来给大家举个例子&#xff0c;假设现在有个问题&#xff0c;需要你在一个只有小写字母的字…

go test相关命令

在 Go 项目中&#xff0c;go test 可以用于运行整个工程中的测试文件。以下是几种方式&#xff1a; 1. 运行当前模块或整个工程的测试 go test ./..../... 表示递归测试所有子目录中的测试文件&#xff08;*_test.go&#xff09;。适用于 Go Modules 或 GOPATH 结构的项目。 …

RocketMQ 详细知识点总结

RocketMQ 详细知识点总结 1. 核心概念 1.1 基础组件 Producer(生产者) 消息的发送者支持同步、异步和单向发送方式提供事务消息功能Consumer(消费者) 消息的接收者支持Push和Pull两种消费模式支持集群消费和广播消费NameServer(命名服务) 路由注册中心无状态节点,可集…

文字也能生成视频?【蓝耘实践】:通义万相2.1文生视频

文字也能生成视频&#xff1f;【蓝耘实践】&#xff1a;通义万相2.1文生视频 上次我们已经介绍了关于在蓝耘云平台实践通义万相的基本玩法&#xff0c;这次将介绍进阶玩法&#xff0c;也就是使用文字来生成视频。 首先我们还是先注册或者登录蓝耘云平台。 通过蓝耘平台进入流…

蓝桥杯 跑步计划

问题描述 小蓝计划在某天的日期中出现 1 时跑 5 千米&#xff0c;否则只跑 1 千米。注意&#xff1a;日期中出现 1 不仅指年月日&#xff0c;也指星期。 请问按照小蓝的计划&#xff0c;2023 年小蓝总共会跑步锻炼多少千米&#xff1f; 例如&#xff1a; 5 月 1 日1 月 13 …

K8S集群新增和删除Node节点(K8s Cluster Adds and Removes Node Nodes)

实战&#xff1a;在已有K8S集群如何新增和删除Node节点 在Kubernetes (K8S) 集群中&#xff0c;Node节点是集群中的工作节点&#xff0c;它们运行着容器的实际实例。管理K8S集群中的Node节点&#xff0c;包括新增和删除节点&#xff0c;是一个常见且重要的操作&#xff0c;可以…