当前位置: 首页 > news >正文

Qt进程间通信

QSharedMemory

共享内存(Shared Memory)是一种进程间通信(Inter-Process Communication, IPC)机制,允许多个进程共享同一块内存区域。共享内存提供了高效的数据交换方式,适用于需要频繁传递大量数据的场景。

Qt中的共享内存机制主要依赖于QSharedMemory类。该类提供了用于创建和管理共享内存区域的接口,允许进程在内存中创建一个共享的数据缓冲区.

使用步骤

  • 创建共享内存:使用QSharedMemory类的create()函数可以创建一个共享内存对象,并指定一个唯一的键(key)来标识共享内存区域。如果该键对应的共享内存已经存在,则会返回false
  • 分配内存:使用QSharedMemory类的attach()函数将共享内存附加到当前进程的地址空间。
  • 写入和读取数据:通过共享内存附加到的地址,进程可以直接读取或写入共享内存中的数据。可以使用任何数据结构,如数组、结构体等来组织共享的数据。
  • 分离和删除共享内存:当进程不再需要访问共享内存时,可以使用QSharedMemory类的detach()函数将共享内存从当前进程的地址空间中分离。而使用QSharedMemory类的remove()函数可以删除共享内存区域,释放相关资源。

跨平台特性差异:

  • windows:内核自动回收,进程退出后内存自动释放
  • linux:QSharedMemory 持有,需显式调用析构函数

示例

写入端

#include<QtCore/QCoreApplication>#include<QSharedMemory>#include<QDebug>#include<QThread>#include<qmath.h>intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);QSharedMemory*shared_mm=newQSharedMemory();shared_mm->setKey("my_shared_data");if(!shared_mm->attach(QSharedMemory::ReadWrite)){shared_mm->create(20,QSharedMemory::ReadWrite);intno=0;QString ret="";while(true){no+=1;shared_mm->lock();ret=QString("shared no:%0").arg(no);memset(shared_mm->data(),0,shared_mm->size());memcpy(shared_mm->data(),ret.toStdString().data(),qMin(ret.size(),shared_mm->size()));shared_mm->unlock();QThread::sleep(2);qDebug()<<ret;}}else{qDebug()<<"app1 attach `my_shared_data` failed!";}returna.exec();}

读取端

#include<QtCore/QCoreApplication>#include<QSharedMemory>#include<QDebug>#include<QThread>#include<qmath.h>intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);QSharedMemory*shared_mm=newQSharedMemory();shared_mm->setKey("my_shared_data");if(!shared_mm->attach(QSharedMemory::ReadWrite)){shared_mm->create(20,QSharedMemory::ReadWrite);intno=0;QString ret="";while(true){no+=1;shared_mm->lock();ret=QString("shared no:%0").arg(no);memset(shared_mm->data(),0,shared_mm->size());memcpy(shared_mm->data(),ret.toStdString().data(),qMin(ret.size(),shared_mm->size()));shared_mm->unlock();QThread::sleep(2);qDebug()<<ret;}}else{qDebug()<<"app1 attach `my_shared_data` failed!";}returna.exec();}

如果是一个进程写,多个进程读的场景,可以考虑内存分页,不同的进程读取不同的内存段

# 示例代码constintPAGE_SIZE=2048;// 内存页2kintapp_page=2;memcpy(shared_mm->data()+2*PAGE_SIZE,ret.toStdString().data(),qMin(ret.size(),shared_mm->size()));

QSystemSemaphore

如果两端都需要写入,需要借助系统信号来控制读、写的时机(信号量为0时,会阻塞线程或进程)。

app1

初始化‘sys_shared_semaphore1’、‘sys_shared_semaphore2’两个信号量,同时启动时初始化‘my_shared_data’共享存储区。

app1向共享存储区写入数据,设置sys_shared_semaphore1的信号量为1;然后等待sys_shared_semaphore2,获取到信号量后读取数据。

#include<QtCore/QCoreApplication>#include<QSharedMemory>#include<QDebug>#include<QThread>#include<QMath.h>#include<QSystemSemaphore>intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);QSystemSemaphoresemaphore1("sys_shared_semaphore1",0);QSystemSemaphoresemaphore2("sys_shared_semaphore2",0);QSharedMemory*shared_mm=newQSharedMemory();shared_mm->setKey("my_shared_data");charbuff[20]={0};if(!shared_mm->attach(QSharedMemory::ReadWrite)){shared_mm->create(20,QSharedMemory::ReadWrite);intno=0;QString ret="";while(true){no+=1;shared_mm->lock();ret=QString("app1 no:%0").arg(no);memset(shared_mm->data(),0,shared_mm->size());memcpy(shared_mm->data(),ret.toStdString().data(),qMin(ret.size(),shared_mm->size()));shared_mm->unlock();semaphore1.release(1);if(semaphore2.acquire()){memset(buff,0,20);shared_mm->lock();memcpy(&buff,shared_mm->constData(),sizeof(buff));qDebug()<<"read sharememory:"<<buff;shared_mm->unlock();}}}else{qDebug()<<"app1 attach `my_shared_data` failed!";}returna.exec();}

app2

与app1差不多,启动后先附加‘my_shared_data’,附加成功表示app1已经启动;然后等待sys_shared_semaphore1信号,获取信号后读取数据。

app2向共享存储区写入数据后,设置sys_shared_semaphore2的信号量为1,此时app1获取信号后可以读取数据。

#include<QtCore/QCoreApplication>#include<QSharedMemory>#include<QDebug>#include<QThread>#include<QMath.h>#include<QSystemSemaphore>intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);QSystemSemaphoresemaphore1("sys_shared_semaphore1",0);QSystemSemaphoresemaphore2("sys_shared_semaphore2",0);QSharedMemory*shared_mm=newQSharedMemory();shared_mm->setKey("my_shared_data");while(true){if(shared_mm->attach(QSharedMemory::ReadWrite))break;QThread::msleep(1000);qDebug()<<"wait sharememory attach...";}intno=0;QString ret="";charbuff[20]={0};while(true){no+=1;if(semaphore1.acquire()){memset(buff,0,20);shared_mm->lock();memcpy(&buff,shared_mm->constData(),sizeof(buff));qDebug()<<"read sharememory:"<<buff;shared_mm->unlock();}shared_mm->lock();ret=QString("app2 no:%0").arg(no);memset(shared_mm->data(),0,shared_mm->size());memcpy(shared_mm->data(),ret.toStdString().data(),qMin(ret.size(),shared_mm->size()));shared_mm->unlock();semaphore2.release(1);}returna.exec();}

QtRO

Qt Remote Object (QtRO)也是一个用于进程间通信(IPC)的模块,专门用于在不同进程或计算机之间交换信息。它在Qt 5.9之后推出,基于Socket封装,兼容LPC(Local Process Communication)和RPC(Remote Process Communication)。

为了实现远程对象调用,QtRO使用了一种基于信号和槽的机制,类似于Qt本地对象之间的通信。

qt工程中,QtRO依赖 network、remoteobjects两个模块

rep文件

rep文件中包含了通信之间定义的接口。

// 文件名:app_rep_intf.rep class AppRemoteInterface { SIGNAL(signalMsg(const QString &)) //server下发消息给client SLOT(int onMsg(const QString &)) //server接收client的消息 }

server

rep_app_rep_intf_source.h 是app_rep_intf.rep生成的

.pro文件中需要添加:

REPC_SOURCE += $$PWD/app_rep_intf.rep

vs 工程中需要设置app_rep_intf.rep属性:out file type:source (Source header)

#pragma once #include <QDebug> #include "rep_app_rep_intf_source.h" class AppRemoteInterface :public AppRemoteInterfaceSource { Q_OBJECT public: AppRemoteInterface(QObject *parent = nullptr) : AppRemoteInterfaceSource() { } virtual int onMsg(const QString & msg); void sendMsgToClient(const QString &msg); signals: void signalRevMsg(const QString &msg); }; #include "appremoteinterface.h" int AppRemoteInterface::onMsg(const QString & msg) { emit signalRevMsg(msg); return 0; } void AppRemoteInterface::sendMsgToClient(const QString &msg) { emit signalMsg(msg); }

main.cpp

#include <QtCore/QCoreApplication> #include <QRemoteObjectHost> #include <QDebug> #include <QTimer> #include "appremoteinterface.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QRemoteObjectHost app_host; app_host.setHostUrl(QUrl("local:apprmt")); AppRemoteInterface *app_int = new AppRemoteInterface(); app_host.enableRemoting(app_int); qDebug() << "server app running...."; QObject::connect(app_int, &AppRemoteInterface::signalRevMsg, [](const QString &msg) { qDebug() << "server recv:" << msg; }); QTimer timer; QObject::connect(&timer, &QTimer::timeout, [app_int]() { app_int->sendMsgToClient("this is server msg!"); }); timer.start(3000); return a.exec(); }

client

rep_app_rep_intf_replica.h 是app_rep_intf.rep生成的

.pro文件中需要添加:

REPC_REPLICA += app_rep_intf.rep

vs 工程中需要设置app_rep_intf.rep属性:out file type:replica (Replica header)

#include<QtCore/QCoreApplication>#include<QRemoteObjectHost>#include<QDebug>#include<QTimer>#include<QMetaObject>#include"rep_app_rep_intf_replica.h"intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);QRemoteObjectNode app_node;AppRemoteInterfaceReplica*app_inf=app_node.acquire<AppRemoteInterfaceReplica>();app_node.connectToNode(QUrl("local:apprmt"));QObject::connect(app_inf,&AppRemoteInterfaceReplica::signalMsg,[](constQString&msg){qDebug()<<"client recv:"<<msg;});QTimer timer;QObject::connect(&timer,&QTimer::timeout,[app_inf](){if(app_inf->isReplicaValid()){app_inf->onMsg("this is client msg");// 直接调用服务端的SOLT}});timer.start(3000);returna.exec();}
http://www.jsqmd.com/news/490778/

相关文章:

  • LeetCode Hot100(68/100)——198. 打家劫舍
  • 【LLM进阶-Agent】13.function call vs mcp vs skills
  • 2025_NIPS_EgoExoBench: A Benchmark for First- and Third-person View Video Understanding in MLLMs
  • 告别绘图软件!Paperxie AI 科研绘图:10 次免费额度,让理工科论文可视化一步到位
  • Tower I3C Host Adapter 使用范例 (20)
  • 【C++】左值引用、右值引用
  • CS二开之睡眠混淆(五)BeaconGate,UDRL,Sleepmask组合拳
  • AI新范式 02|拆解世界模型:它是如何理解物理规律的?
  • WebRTC QoS方法之NetEQ在流量卡弱网应用下失效
  • Java基础-1
  • 2025_NIPS_Scaling RL to Long Videos
  • 【Dv3Admin】FastCRUD MD编辑器操作
  • open claw安装在windows wsl中教程
  • HDOJ 课程例题记录
  • 第三方 API 调用 OpenClaw 出现 LLM request timed out 的解决方案
  • openclaw+qwen(笔记,非教程)
  • 讲讲普通小轿车驾驶证报考流程及费用,西安哪家驾校好? - mypinpai
  • UE5C++Part2--几种常见的变量类型
  • 企业级RustDesk私有化部署:Docker Swarm集群方案与安全加固指南
  • (85页PPT)某著名企业贝因美IT规划咨询报告(附下载方式)
  • Simulink仿真漂移机理分析(二):相图分析
  • R轻松玩转Excel数据
  • 课程记录:Windows2
  • 高德地图混合部署实战:离线瓦片与在线API的智能切换策略
  • 西安国文驾校二轮摩托车考驾照口碑如何,值得推荐吗 - 工业品牌热点
  • 探讨专业的精密锻造公司,三邑锻造在全国排名第几? - 工业推荐榜
  • 【一篇即毕业系列】C++的引用从基础到通天
  • 仅剩72小时!生态环境部新发布的《污染预测模型R实现规范》(HJ 1308-2024)强制适配倒计时(含兼容性迁移速查表)
  • 2026 本科生论文工具盘点:9 款 AI 工具搞定初稿 / 绘图 / 排版 / AI 率
  • leetcode 1389. Create Target Array in the Given Order 按既定顺序创建目标数组-耗时100