Qt 进程间通信(IPC)全方案
Qt 提供多套跨平台 IPC 方案 ,按使用难度、性能、场景分类整理,附用法、优缺点、示例,适配 Windows/Linux/macOS。
一、方案总览(选型速查表)
表格
| 方案 | 跨平台 | 适用场景 | 性能 | 复杂度 |
|---|---|---|---|---|
| QLocalSocket / QLocalServer | 全平台 | 本机进程通信、大数据、实时交互 | 高 | 低 |
| QSharedMemory 共享内存 | 全平台 | 超大内存数据、只读 / 低频交互 | 极高 | 中 |
| QProcess + 标准 IO | 全平台 | 主进程调用子进程、简单文本交互 | 中 | 极低 |
| Qt D-Bus | Linux/macOS (部分) | Linux 桌面进程调用、系统服务 | 中 | 中高 |
| TCP Socket (QTcpSocket/QTcpServer) | 全平台 | 跨机器 + 本机通用、网络 / 进程二合一 | 高 | 中 |
| 信号量 / 管道 / 文件 | 全平台 | 简单标记、少量数据、临时交互 | 低 | 低 |
日常开发首选: 本机高频通信 → QLocalSocket 超大块数据共享 → QSharedMemory 拉起子进程 + 简单传参 → QProcess Linux 桌面程序 / 系统交互 → D-Bus
二、逐个方案实战(附可运行代码)
1. QLocalSocket / QLocalServer(最推荐,本机进程通信首选)
基于本地命名管道 ,纯 Qt 封装,用法和 TCP Socket 几乎一致,无端口冲突、安全性高、速度快。
服务端(被连接进程)
cpp
运行
#include <QLocalServer>
#include <QLocalSocket>
#include <QDebug>
class IpcServer : public QObject
{
Q_OBJECT
public:
QLocalServer *m_server;
QLocalSocket *m_clientSocket = nullptr;
IpcServer()
{
m_server = new QLocalServer(this);
// 清理残留同名服务(防止上次崩溃残留)
QLocalServer::removeServer("MyIpcServer");
if (!m_server->listen("MyIpcServer"))
{
qDebug() << "服务启动失败:" << m_server->errorString();
return;
}
qDebug() << "本地服务已启动";
connect(m_server, &QLocalServer::newConnection, this, &IpcServer::onNewConnect);
}
private slots:
void onNewConnect()
{
m_clientSocket = m_server->nextConnection();
qDebug() << "客户端已连接";
connect(m_clientSocket, &QLocalSocket::readyRead, this, &IpcServer::onReadData);
connect(m_clientSocket, &QLocalSocket::disconnected, m_clientSocket, &QLocalSocket::deleteLater);
// 回复客户端
m_clientSocket->write("Hello Client from Server!");
}
void onReadData()
{
QByteArray data = m_clientSocket->readAll();
qDebug() << "收到数据:" << data;
}
};
客户端(主动连接进程)
cpp
运行
#include <QLocalSocket>
#include <QDebug>
class IpcClient : public QObject
{
Q_OBJECT
public:
QLocalSocket *m_socket;
IpcClient()
{
m_socket = new QLocalSocket(this);
m_socket->connectToServer("MyIpcServer");
connect(m_socket, &QLocalSocket::connected, [](){
qDebug() << "连接服务端成功";
});
connect(m_socket, &QLocalSocket::readyRead, this, &IpcClient::onRead);
connect(m_socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::errorOccurred),
this, &IpcClient::onError);
}
// 发送数据
void sendMsg(const QString &msg)
{
if(m_socket->isOpen())
m_socket->write(msg.toUtf8());
}
private slots:
void onRead()
{
QByteArray data = m_socket->readAll();
qDebug() << "客户端收到:" << data;
}
void onError(QLocalSocket::LocalSocketError err)
{
qDebug() << "连接错误:" << m_socket->errorString();
}
};
特点
- 纯内存通信,速度快,支持二进制、大数据流
- 只限于本机,不会暴露到外网
- 读写异步,配合
readyRead使用,写法成熟稳定
2. QSharedMemory 共享内存(超大块数据首选)
多进程共享同一块物理内存 ,数据零拷贝,适合:图像、波形、大缓存、高频大数据。 配合 QSystemSemaphore 做同步互斥,防止读写冲突。
写入进程(创建共享内存)
cpp
运行
#include <QSharedMemory>
#include <QSystemSemaphore>
#include <QDebug>
void writeSharedMem()
{
// 信号量:保证同步
QSystemSemaphore sem("MySem", 1);
sem.acquire(); // 加锁
QSharedMemory shm("MyShareMem");
// 创建 1024 字节共享内存
if (!shm.create(1024))
{
qDebug() << "创建失败:" << shm.errorString();
sem.release();
return;
}
// 写入数据
char *data = (char*)shm.data();
QString str = "This is Shared Memory Data";
memcpy(data, str.toUtf8().data(), str.size());
sem.release(); // 解锁
qDebug() << "数据写入共享内存完成";
}
读取进程(挂载共享内存)
cpp
运行
void readSharedMem()
{
QSystemSemaphore sem("MySem", 1);
sem.acquire();
QSharedMemory shm("MyShareMem");
if (!shm.attach())
{
qDebug() << "挂载失败:" << shm.errorString();
sem.release();
return;
}
char *data = (char*)shm.data();
qDebug() << "读取数据:" << QString(data);
shm.detach(); // 脱离共享内存
sem.release();
}
关键点
- Key 必须一致 :
MyShareMem、MySem两端完全相同 - 必须用 QSystemSemaphore 做互斥,否则多进程同时读写会乱码 / 崩溃
- 进程退出前
detach(),主进程退出后共享内存自动释放 - 优点:速度天花板级别,适合图像、视频、海量点位数据
3. QProcess + 标准输入输出(父子进程简单通信)
适合:主程序启动子进程,传递参数、接收子进程控制台输出。 纯文本交互,最简单,无需额外 IPC 组件。
主进程(启动子进程 + 收发数据)
cpp
运行
#include <QProcess>
#include <QDebug>
QProcess *m_process;
void startSubProcess()
{
m_process = new QProcess(this);
// 启动另一个 Qt 程序路径
m_process->start("./sub_app");
// 接收子进程输出
connect(m_process, &QProcess::readyReadStandardOutput, [=](){
QString out = m_process->readAllStandardOutput();
qDebug() << "子进程输出:" << out;
});
// 向子进程写入数据
m_process->write("Hello SubProcess\n");
}
子进程(读取标准输入)
cpp
运行
// 子进程 main 函数中
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream in(stdin);
QString msg = in.readLine();
qDebug() << "子进程收到:" << msg;
// 输出给父进程
QTextStream out(stdout);
out << "I am Sub Process" << endl;
return a.exec();
}
特点
- 用法最简单,适合调用外部程序
- 基于管道,不适合二进制大数据、高频交互
- 跨平台通用
4. QTcpSocket / QTcpServer(网络 Socket,本机 + 跨机器通用)
把本机进程当成 127.0.0.1 网络通信 ,写法和网络编程一致。 适合:未来可能跨机器部署、不想区分本地 / 网络两套代码。
cpp
运行
// 服务端
QTcpServer *tcpServer = new QTcpServer(this);
tcpServer->listen(QHostAddress::LocalHost, 8888);
// 客户端
QTcpSocket *tcpClient = new QTcpSocket(this);
tcpClient->connectToHost(QHostAddress::LocalHost, 8888);
缺点:占用端口,可能端口冲突;本机性能略弱于
QLocalSocket。
5. D-Bus(Linux 专属)
Linux 桌面环境标准 IPC,常用于:
- 桌面通知、系统服务调用
- 多个桌面组件互相调用
仅 Linux 主流使用 ,Windows/macOS 基本不用,Qt 需开启 dbus 模块:
qmake
QT += dbus
适合做远程方法调用 (RPC),可以直接调用对方类的槽函数,语法类似信号槽。
三、场景化选型建议(直接照选)
-
同机器两个独立程序,频繁收发消息 / 二进制数据 → QLocalSocket(首选,稳定、简单、高效)
-
多进程共享一张大图、波形数据、大缓冲区 → QSharedMemory + QSystemSemaphore
-
主程序启动子进程,简单传参、看日志输出 → QProcess 标准 IO
-
程序未来要支持跨电脑通信,本地 / 网络一套代码 → QTcpSocket 本地回环 127.0.0.1
-
Linux 桌面软件、和系统服务 / 桌面组件交互 → D-Bus
-
极简单标记、少量文本 → 临时文件、注册表 (Windows)、环境变量(不推荐做正式 IPC)
四、通用避坑要点
-
命名统一 QLocalServer、QSharedMemory、QSystemSemaphore 的名称两端必须完全一致。
-
残留清理 程序崩溃会残留本地服务 / 共享内存,启动时执行:
cpp
运行
QLocalServer::removeServer("xxx"); -
多线程 Socket / 共享内存不要跨线程直接操作,遵循 Qt 线程规则,数据转发到主线程。
-
二进制数据 优先
QLocalSocket/ 共享内存,不要用 QProcess 标准 IO(易乱码、分包)。 -
Release 模式 IPC 大量数据传输时,Debug 会明显变慢,正式部署务必 Release。