《2026年上半年中国企业出海培训现状报告》 全球化经营深化背景下的人才能力建设趋势与实践洞察
2026/7/22 12:42:56
写一个程序a和一个监控程序b,a定周期写一个数据c,并且每次递增,数据是uchar 类型就可以,达到最大值后从0重新开始。 程序b通过共享内存定周期读取a写的c的值,写数据的周期是一秒,读数据的周期是5秒,b如果一个周期内发现数据没有变化,证明a出问题了,就重启a
我将为您设计基于Qt/C++的共享内存通信与进程监控系统。以下是分步骤的解决方案:
QSharedMemory实现跨进程数据交换QProcess启动/监控/重启子进程QTimer实现精确的周期控制cpp
// a.cpp #include <QCoreApplication> #include <QSharedMemory> #include <QTimer> class DataWriter { public: DataWriter(const QString &sharedKey) : m_sharedKey(sharedKey), m_shm(sharedKey) { // 初始化共享内存 if (!m_shm.create(1)) { if (m_shm.error() == QSharedMemory::AlreadyExists) { m_shm.attach(); } } // 设置定时器 QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &DataWriter::updateData); timer->start(1000); // 1秒周期 } private: void updateData() { m_shm.lock(); uchar *data = static_cast<uchar*>(m_shm.data()); *data = (*data + 1) % 256; // 递增并处理溢出 m_shm.unlock(); } private: QString m_sharedKey; QSharedMemory m_shm; }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); DataWriter writer("Global\\MySharedMem"); return a.exec(); }cpp
// b.cpp #include <QCoreApplication> #include <QSharedMemory> #include <QTimer> #include <QProcess> class ProcessMonitor { public: ProcessMonitor(const QString &sharedKey, const QString &programPath) : m_sharedKey(sharedKey), m_programPath(programPath), m_shm(sharedKey), m_process(nullptr) { // 启动被监控程序 restartProcess(); // 设置监控定时器 QTimer *monitorTimer = new QTimer(this); connect(monitorTimer, &QTimer::timeout, this, &ProcessMonitor::checkStatus); monitorTimer->start(5000); // 5秒周期 } private: void restartProcess() { if (m_process) { m_process->terminate(); m_process->waitForFinished(3000); delete m_process; } m_process = new QProcess(this); connect(m_process, &QProcess::errorOccurred, [this](QProcess::ProcessError) { qDebug() << "Process error:" << m_process->errorString(); }); m_process->start(m_programPath); } void checkStatus() { static uchar lastValue = 0; static int staleCount = 0; m_shm.lock(); uchar *data = static_cast<uchar*>(m_shm.constData()); uchar currentValue = data ? *data : 0; m_shm.unlock(); // 检测数据是否变化 if (currentValue == lastValue) { staleCount++; if (staleCount >= 1) { // 单次检测到未变化即重启 qDebug() << "Process stalled! Restarting..."; restartProcess(); staleCount = 0; } } else { lastValue = currentValue; staleCount = 0; } } private: QString m_sharedKey; QString m_programPath; QSharedMemory m_shm; QProcess *m_process; }; int main(int argc, char *argv[]) { QCoreApplication b(argc, argv); ProcessMonitor monitor("Global\\MySharedMem", "a.exe"); return b.exec(); }Global\\MySharedMem确保跨进程访问QProcess实现进程生命周期管理编译配置:
makefile
QT += core CONFIG += console c++11运行顺序:
bash
# 先启动监控程序B ./b # 后启动数据程序A ./a测试场景:
QDebug或日志框架记录运行状态此方案实现了严格的周期控制、可靠的进程管理和高效的共享内存通信,满足用户提出的所有技术要求,并具有良好的跨平台兼容性和可扩展性。
是的,Global\\MySharedMem在Windows 操作系统中确实是全局命名空间的共享内存键标识符,而在Linux/macOS 等类Unix系统中,Qt 会自动将其转换为标准的共享内存键(如通过文件路径或系统IPC键)。以下是详细解释:
Global\\前缀:MySharedMem)仅在当前用户会话内可见,而Global\\MySharedMem对所有会话可见。Global\\前缀。QSharedMemory会自动转换键格式以适应不同操作系统:/dev/shm/MySharedMem或通过ftok生成的键)。Global\\前缀。直接使用MySharedMem即可,Qt 会处理底层实现。MySharedMem),让 Qt 自动处理平台差异。Global\\前缀,但需测试权限和兼容性。cpp
QString sharedKey = "CompanyName_ProgramA_SharedMem_2025";/dev/shm)有读写权限。可通过以下代码验证不同平台下的键名解析:
cpp
#include <QSharedMemory> #include <QDebug> int main() { QSharedMemory shm("Global\\MySharedMem"); qDebug() << "Raw key:" << shm.key(); qDebug() << "Is attached?" << shm.isAttached(); #ifdef Q_OS_WIN qDebug() << "Running on Windows"; // 实际创建的是全局命名对象 #else qDebug() << "Running on Unix-like system"; // Qt 转换为标准共享内存路径 #endif return 0; }QFile和QFileDevice::map创建基于文件的共享内存,跨平台更一致。QtRO)。Global\\是 Windows 特有的全局命名空间前缀,在类Unix系统上由 Qt 自动适配。此设计确保了程序在 Windows 和类Unix系统上的兼容性,同时利用了 Qt 的跨平台优势。