C++ 基于boost::interprocess共享内存的进程间信号通知方案咨询
进程间共享内存更新通知实现方案
场景说明
现有两个并行运行的进程,分别负责向共享内存写数据、从共享内存读数据,已基于boost::interprocess实现共享内存读写逻辑,需要实现写操作完成后实时通知读进程数据更新,适配实时数据流传输场景。
现有实现代码(写进程)
//Writer #include <boost/interprocess/shared_memory_object.hpp> #include <boost/interprocess/windows_shared_memory.hpp> #include <boost/interprocess/mapped_region.hpp> #include <iostream> namespace ip = boost::interprocess; class SharedMemory { public: template<typename OpenOrCreate> SharedMemory(OpenOrCreate criteria, const char* name, ip::mode_t mode, size_t size) : name_(name), sm_(std::make_shared<ip::windows_shared_memory>(criteria, name, mode, size)) { } template<typename OpenOrCreate> SharedMemory(OpenOrCreate criteria, const char* name, ip::mode_t mode) : name_(name), sm_(std::make_shared<ip::windows_shared_memory>(criteria, name, mode)) { } std::shared_ptr<ip::windows_shared_memory> getSM() { return sm_; } private: std::function<void()> destroyer_; std::string name_; std::shared_ptr<ip::windows_shared_memory> sm_; }; int main() { SharedMemory creator(ip::create_only, "SharedMemory", ip::read_write, 10); ip::mapped_region region(*creator.getSM(), ip::read_write); std::memset(region.get_address(), 1, region.get_size()); int status = system("reader.exe"); std::cout << status << std::endl; }
推荐实现方案
方案1:使用boost::interprocess自带同步组件(无额外依赖,优先推荐)
直接使用库自带的named_mutex+named_condition组合,和现有共享内存逻辑完全兼容:
写进程修改逻辑
- 新增头文件引入:
#include <boost/interprocess/sync/named_mutex.hpp> #include <boost/interprocess/sync/named_condition.hpp>
- 写数据前后的同步逻辑:
int main() { // 启动前先清理可能残留的同步对象,避免异常退出导致的启动失败 ip::named_mutex::remove("shm_mutex"); ip::named_condition::remove("shm_cond"); SharedMemory creator(ip::create_only, "SharedMemory", ip::read_write, 10); ip::mapped_region region(*creator.getSM(), ip::read_write); // 创建命名互斥锁和条件变量 ip::named_mutex mutex(ip::create_only, "shm_mutex"); ip::named_condition cond(ip::create_only, "shm_cond"); // 写数据 { ip::scoped_lock<ip::named_mutex> lock(mutex); std::memset(region.get_address(), 1, region.get_size()); } // 解锁后再发送通知,减少不必要的阻塞 cond.notify_one(); // 其他业务逻辑... }
读进程修改逻辑
int main() { SharedMemory opener(ip::open_only, "SharedMemory", ip::read_only); ip::mapped_region region(*opener.getSM(), ip::read_only); // 打开同名的互斥锁和条件变量 ip::named_mutex mutex(ip::open_only, "shm_mutex"); ip::named_condition cond(ip::open_only, "shm_cond"); { ip::scoped_lock<ip::named_mutex> lock(mutex); // 等待写进程通知 cond.wait(lock); // 收到通知后读取数据 char* data = static_cast<char*>(region.get_address()); // 处理数据逻辑... } // 其他业务逻辑... }
方案2:Windows原生命名事件(仅Windows平台,用法更简单)
因为当前用的是windows_shared_memory,仅运行在Windows平台的话可以直接用系统API的命名事件,逻辑更轻量:
- 写进程调用
CreateEventA创建命名事件,写完数据后调用SetEvent触发通知 - 读进程调用
OpenEventA打开同名事件,调用WaitForSingleObject等待事件触发后再读数据
方案3:命名信号量
如果逻辑更简单不需要额外条件判断,也可以用boost::interprocess::named_semaphore,写进程写完调用post(),读进程调用wait()等待即可。
注意事项
- 实时数据流场景可以在共享内存中新增一个序列号字段,读进程被唤醒后比对序列号,避免因信号丢失导致的漏读问题
- 同步对象的名称要全局唯一,避免和其他进程冲突
- 进程退出前可以主动清理创建的同步对象,避免残留影响下次启动
内容的提问来源于stack exchange,提问作者Eduard Rostomyan
相关产品推荐
相关产品推荐

