Qt/C++进程间通信:QSharedMemory 使用详解(附演示Demo)

embedded/2025/1/16 21:16:07/

在开发跨进程应用程序时,进程间通信(IPC)是一个关键问题。Qt 框架提供了多种 IPC 技术,其中 QSharedMemory 是一种高效的共享内存方式,可以实现多个进程之间快速交换数据。本文将详细讲解 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()) {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. 注意事项

  1. 共享内存大小

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

    • 在操作共享内存前,必须调用 lock() 进行锁定,以避免数据竞争。
    • 使用完成后,必须调用 unlock() 解锁。
  3. 错误处理

    • 使用 error()errorString() 检查共享内存的状态。
  4. 进程退出

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

7. 总结

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


http://www.ppmy.cn/embedded/154486.html

相关文章

用 Python 自动化处理日常任务

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

使用 selenium-webdriver 开发 Web 自动 UI 测试程序

优缺点 优点 有时候有可能一个改动导致其他的地方的功能失去效果&#xff0c;这样使用 Web 自动 UI 测试程序可以快速的检查并定位问题&#xff0c;节省大量的人工验证时间 缺点 增加了维护成本&#xff0c;如果功能更新过快或者技术更新过快&#xff0c;维护成本也会随之提高…

【Linux】sed编辑器二

一、处理多行命令 sed编辑器有3种可用于处理多行文本的特殊命令。 N&#xff1a;加入数据流中的下一行&#xff0c;创建一个多行组进行处理&#xff1b;D&#xff1a;删除多行组中的一行&#xff1b;P&#xff1a;打印多行组中的一行。 1、next命令&#xff1a;N 单行next命…

【SpringSecurity】SpringSecurity安全框架授权

授权 权限系统要实现的效果&#xff1a;不同的用户可以使用不同的功能。 在后台进行用户权限的判断&#xff0c;判断当前用户是否有相应的权限&#xff0c;必须具有所需权限才能进行相应的操作。 在 SpringSecurity 中&#xff0c;默认使用 FilterSecurityInterceptor 进行权…

uni-app (接入智谱清言语言模型)

1.技术说明 uni-app、智谱清言、XMLHttpRequest、marked 2.实现原理 此处实现原理为前端直接请求返还数据结果&#xff0c;未经后端进行处理&#xff0c;如AI接口有变化&#xff0c;请根据接口文档进行修改&#xff0c;通义千问AI同理。 XMLHttpRequest发起请求->监听数…

JavaSwing游戏开发之Camera原理

package org.timer;import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; import java.util.List; import java.util.Random;public class GameCameraWithObjects extends JPanel implements KeyListener {// 游戏世界大小private …

js解决 Number失精度问题

const updatePromises adinfo.rows.map(async item > {const cwf await uniCloud.httpclient.request("https://api.oceanengine.com/open_api/v3.0/project/list/", {method: GET,data: {advertiser_id: item.account_id},// 1. 指定text数据格式dataType: tex…

R语言基础| 方差分析

写在前面 方差分析&#xff08;ANOVA&#xff0c;Analysis of Variance&#xff09;是统计学中一种用来比较三个或三个以上样本均值是否存在显著差异的方法。方差分析基于样本数据的方差来判断整体均值之间的差异&#xff0c;是处理多个样本组数据对比问题的常用技术。 方差分析…