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.rhkb.cn/news/39739.html

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

相关文章

快速入手-基于Django的mysql配置(三)

Django开发操作数据库更简单&#xff0c;内部提供了ORM框架。比如mysql&#xff0c;旧版本用pymysql对比较多&#xff0c;新的版本采用mysqlclient。 1、安装mysql模块 pip install mysqlclient 2、Django的ORM主要做了两件事 &#xff08;1&#xff09;CRUD数据库中的表&am…

ETL:数据清洗、规范化和聚合的重要性

在当今这个数据呈爆炸式增长的时代&#xff0c;数据已成为企业最为宝贵的资产之一。然而&#xff0c;数据的海量增长也伴随着诸多问题&#xff0c;如数据来源多样、结构复杂以及质量问题等&#xff0c;这些问题严重阻碍了数据的有效处理与深度分析。在此背景下&#xff0c;ETL&…

【leetcode hot 100 208】实现Trie(前缀树)

解法一&#xff1a;字典树 Trie&#xff0c;又称前缀树或字典树&#xff0c;是一棵有根树&#xff0c;其每个节点包含以下字段&#xff1a; 指向子节点的指针数组 children。对于本题而言&#xff0c;数组长度为 26&#xff0c;即小写英文字母的数量。此时 children[0] 对应小…

PyTorch生成式人工智能实战:从零打造创意引擎

PyTorch生成式人工智能实战&#xff1a;从零打造创意引擎 0. 前言1. 生成式人工智能1.1 生成式人工智能简介1.2 生成式人工智能技术 2. Python 与 PyTorch2.1 Python 编程语言2.2 PyTorch 深度学习库 3. 生成对抗网络3.1 生成对抗网络概述3.2 生成对抗网络应用 4. Transformer4…

vue中上传接口file表单提交二进制文件流

1.使用elementui上传组件 要做一个选择文件后&#xff0c;先不上传&#xff0c;等最后点击确定后&#xff0c;把file二进制流及附加参数一起提交上去。 首先使用elementui中的上传组件&#xff0c;设置auto-uploadfalse&#xff0c;也就是选择文件后不立刻上传。 <el-uplo…

深入解析 Java Stream API:筛选根节点的优雅实现!!!

&#x1f680; 深入解析 Java Stream API&#xff1a;筛选根节点的优雅实现 &#x1f527; 大家好&#xff01;&#x1f44b; 今天我们来聊聊 Java 8 中一个非常常见的操作&#xff1a;使用 Stream API 从 List 中筛选出特定条件的元素。&#x1f389; 具体来说&#xff0c;我…

推荐1款简洁、小巧的实用收音机软件,支持手机和电脑

聊一聊 没想到现在还有人喜欢听广播。 我一直以为听广播必须要用那种小广播机才可以。 原来手机或电脑上也是可以的。 今天给大家分享一款可以在电脑和手机上听广播的软件。 软件介绍 龙卷风收音机 电台广播收音机分电脑和手机两个版本。 电脑端无需安装&#xff0c;下载…

金桔网桥路由版3

上一集我们讲到了二层云交换机&#xff0c;我把在云上搭建的桥接模式的VPN服务器称为二层云交换机。 那么现在我家到办公室的网络结构就变成这样的&#xff0c; 这样的好处就是我的电视盒子通过网线看电视&#xff0c;走的是OpenWrt路由器通过二层云交换机由办公室的OpenWrt路由…

常见中间件漏洞攻略-Tomcat篇

一、 CVE-2017-12615-Tomcat put方法任意文件写入漏洞 第一步&#xff1a;开启靶场 第二步&#xff1a;在首页抓取数据包&#xff0c;并发送到重放器 第三步&#xff1a;先上传尝试一个1.txt进行测试 第四步&#xff1a;上传后门程序 第五步&#xff1a;使用哥斯拉连接 二、后…

计算机复试面试

数据库 1.设计过程/设计步骤 1.需求分析&#xff1a;明确客户需求&#xff0c;确定系统边界&#xff0c;生成数据字典 2.概念结构设计&#xff1a;将用户需求抽象为概念模型&#xff0c;绘制e-r图 3.逻辑结构设计&#xff1a;将e-r图转化为dbms相符合的逻辑结构&#xff0c;db…

【零基础学python】python基础语法(一)

前言&#xff1a;Python 是当今最受欢迎的编程语言之一&#xff0c;其广泛应用于 人工智能、数据科学、Web 开发、自动化 等多个领域。它以 简洁的语法、强大的标准库 和 跨平台兼容性 深受开发者喜爱。作为 机器学习和大数据的首选语言&#xff0c;Python 在学术研究、金融分析…

数据类设计_图片类设计之8_自由图形类设计_(前端架构)

前言 学的东西多了,要想办法用出来.C和C是偏向底层的语言,直接与数据打交道.尝试做一些和数据方面相关的内容 引入 前面的内容都是矩阵图形类,现在讨论自由图形类设计 矩阵图形类和自由图形类的差别 左图为矩阵图形类对象,右图为自由图形类对象.矩阵图形类对象单独占据一个矩…

【学习记录】大模型微调之使用 LLaMA-Factory 微调 Qwen系列大模型,可以用自己的数据训练

一、LoRA微调的基本原理 1、基本概念 LoRA&#xff08;Low-Rank Adaptation&#xff09;是一种用于大模型微调的技术&#xff0c;通过引入低秩矩阵来减少微调时的参数量。在预训练的模型中&#xff0c;LoRA通过添加两个小矩阵B和A来近似原始的大矩阵ΔW&#xff0c;从而减少需…

绿盟CSSP靶场-将已有虚拟机创建为新镜像作为新虚拟机模板

将部署了自定义软件的虚拟机&#xff0c;【保持镜像】将这个在运的虚拟机存为一个新的镜像。 为了保证上传的镜像是完整的&#xff0c;勾选【全量镜像】。 等待镜像上传完成&#xff0c;可以看到刚刚上传的镜像&#xff0c;状态也为已上传。 将镜像从私有改为共享&#xff0c;…

VMWare Ubuntu 详细安装教程

VMWare Ubuntu 详细安装教程 一、下载安装VMware二、下载 Ubuntu 镜像文件三、安装 Ubuntu四、开启虚拟机 一、下载安装VMware 官网下载地址https://www.vmware.com/products/desktop-hypervisor/workstation-and-fusion知乎大佬的博客原文&#xff0c;含下载地址https://zhua…

嵌入式c学习八

练习 一、指针数组与数组指针 #include <stdio.h>int main() {//c是一个指针数组&#xff0c;里面有4个元素每个元素都是指针 char *c[] {"hello", "world", "homed", "gotogo"}; //cp是指针数组&#xff0c;有4个元素&#…

LLaMA-Factory微调大模型

LLaMA-Factory安装 github 下载 LLaMA-Factory项目 创建虚拟环境 conda create -n llama_factory python3.10 激活 activate llama_factorytorch 安装 conda install pytorch2.3.1 torchvision0.18.1 torchaudio2.3.1 pytorch-cuda12.1 -c pytorch -c nvidia依赖安装 …

第一讲 | 解锁C++编程能力:基础语法解析

C入门基础 一、C的第一个程序二、命名空间三、C输入&输出四、缺省参数/默认参数五、函数重载六、引用1.引用的特性2.引用的使用引用做返回值场景 3.const引用只有指针和引用涉及权限放大、缩小的问题&#xff0c;普通变量没有 4.指针和引用的关系 七、inline八、nullptr 一…

【颠覆性缓存架构】Caffeine双引擎缓存实战:CPU和内存双优化,命中率提升到92%,内存减少75%

千万级QPS验证&#xff01;Caffeine智能双缓存实现 92%命中率&#xff0c;内存减少75% 摘要&#xff1a; 本文揭秘千万级流量场景下的缓存革命性方案&#xff01;基于Caffeine打造智能双模式缓存系统&#xff0c;通过冷热数据分离存储与精准资源分配策略&#xff0c;实现CPU利…

JVM 03

今天是2025/03/24 15:21 day 11 总路线请移步主页Java大纲相关文章 今天进行JVM 5,6 个模块的归纳 首先是JVM的相关内容概括的思维导图 5. 优化技术 JVM通过多种优化技术提升程序执行效率&#xff0c;核心围绕热点代码检测和编译优化实现动态性能提升。 热点代码检测 JVM…