c++怎么实现进程间通信共享内存_c++ Windows/Linux共享内存创建【详解】


Windows用CreateFileMapping+MapViewOfFile、Linux用shm_open+mmap实现共享内存,二者均需注意大小设置、错误处理、同步机制及跨平台兼容性,且共享内存中不可存放std::string等非平凡类型。

Windows 下用 CreateFileMappingMapViewOfFile 创建共享内存

Windows 原生共享内存依赖内存映射文件(Memory-Mapped File),即使不关联磁盘文件,也能通过 INVALID_HANDLE_VALUE 创建纯内存段。关键不是“文件”,而是“映射对象”。

常见错误是传错 dwMaximumSizeHigh/dwMaximumSizeLow —— 它们合起来是 64 位大小,但多数场景用不到高位,直接设为 0 即可;若实际大小超 4GB,才需拆分赋值。

  • CreateFileMapping 返回 NULL 时,务必调用 GetLastError() 判断原因:权限不足(ERROR_ACCESS_DENIED)、名字冲突(ERROR_ALREADY_EXISTS)或内存不足(ERROR_NOT_ENOUGH_MEMORY)都得区分处理
  • 映射视图前必须确保 hMap 有效,且 MapViewOfFiledwNumberOfBytesToMap 不能超过创建时声明的大小
  • 多个进程访问同一块共享内存时,**没有内置同步机制**,必须额外配 CreateEventCreateMutex 控制读写顺序
HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, TEXT("MySharedMem"));
if (hMap == NULL) {
    // 处理错误
}
LPVOID pMem = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 1024);
if (pMem == NULL) {
    CloseHandle(hMap);
}

Linux 下用 shm_open + mmap 创建 POSIX 共享内存

Linux 推荐用 POSIX 标准接口:shm_open 创建/打开一个共享内存对象(本质是 /dev/shm/ 下的虚拟文件),再用 mmap 映射进地址空间。它比 sysv shmshmget 系列)更现代、路径可控、权限清晰。

容易忽略的是 shm_openoflag 参数:跨进程通信必须带 O_RDWR,首次创建还要加 O_CREAT;同时 mode(如 0666)决定其他用户能否打开——若不设,可能被 umask 截断导致权限不足。

  • shm_open 返回的 fd 必须在 mmapclose(),否则资源泄漏(fd 不释放,但映射仍有效)
  • mmaplength 必须与 ftruncate 设置的大小一致,否则读写越界或 SEGV
  • 进程退出时不自动销毁共享内存,需显式调用 shm_unlink(仅删除名字,已映射的仍可用)
int fd = shm_open("/my_shm", O_CREAT | O_RDWR, 0666);
ftruncate(fd, 1024);
void* ptr = mmap(nullptr, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd); // fd 可关,ptr 仍有效

跨平台封装要注意的兼容性陷阱

Windows 和 Linux 的共享内存 API 差异大,强行抽象成统一接口容易踩坑。最现实的做法是按平台条件编译,或只封装“创建/映射/销毁”三步,把同步逻辑完全交给上层。

典型陷阱包括:

  • 名字格式:Windows 支持任意字符串(如 "MyMem"),Linux 的 shm_open 要求以 / 开头且不能含其它斜杠("/my_mem" 合法,"/a/b" 非法)
  • 大小限制:Windows 单个映射上限约 2GB(32 位进程),Linux 默认 /dev/shm 大小常为 64MB,可通过 mount -o remount,size=2G /dev/shm 调整
  • 生命周期管理:Linux 的 shm_unlink 类似于 Windows 的 CloseHandle + 名字注销,但 Windows 没有等价的“仅删名不关句柄”操作

为什么共享内存里不能放 std::string 或虚函数对象

共享内存本质是一段裸字节区域,所有数据必须是 trivially copyable,且地址无关。一旦结构体里包含 std::stringstd::vector、指针、虚表指针或非 POD 成员,就绝不能直接 memcpy 进去。

例如:struct Data { std::string name; int id; }; —— name 内部指针指向堆内存,其他进程无法访问;虚函数对象的 vptr 指向本进程的虚表,跨进程失效。

  • 正确做法是用固定长度 C 风格数组(char name[64])、手动序列化、或使用 boost::interprocess 提供的容器(如 boost::interprocess::basic_string
  • 若必须动态结构,建议只存偏移量+长度,把真实数据也布局在同一块共享内存中(即“内存池 + 相对指针”模式)
  • 所有字段必须显式对齐(alignas(8)),避免不同编译器填充差异导致读写错位

共享内存本身不难创建,难的是让两个独立进程安全、稳定、一致地解释同一片内存里的比特。类型布局、生命周期、同步粒度,这三样漏掉任何一环,都会在某个并发时机突然崩掉。


# linux  # windows  # app  # 字节  # access  # c++  # win  # nas  # 同步机制  # 为什么  # red  # asic  # String  # NULL  # 封装  # 字符串  # 结构体  # char  # int  # 指针  # 虚函数  # 接口  #   # Length  # Struct  # 并发  # 对象  # 的是  # 首次  # 多个  # 句柄  # 也能  # 设为  # 要注意  # 再用  # 可通过  # 都得 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: Win10怎样清理C盘Steam游戏缓存_Win10清理Steam游戏缓存步骤【步骤】  Win11怎么关闭内容自适应亮度_Windows11显示设置CABC关闭  Win11任务栏颜色怎么改_Win11自定义任务栏配色设置【美化】  Win11如何设置开机问候语 Win11修改登录界面提示【技巧】  C++如何使用std::async进行异步编程?(future用法)  php本地部署后session无法保存_session存储路径与权限设置技巧【技巧】  本地php环境出现502错误_nginx或apache502badgateway解决技巧【解答】  win11 OneDrive怎么彻底关闭 Win11禁用并卸载OneDrive教程【分享】  php增删改查在php8里有什么变化_新特性对curd的影响【指南】  Windows Defender扫描失败怎么办_安全模块损坏修复方式  如何在 Go 中正确反序列化 XML 多节点数组(解决仅解析首个元素的问题)  Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤  php串口通信波特率怎么选_根据硬件手册设置正确波特率【方法】  Django密码修改后会话失效的解决方案  Win11怎么开启专注模式_Windows11时钟应用Focus Session  如何在Golang中使用encoding/gob序列化对象_存储和传输数据  Python对象比较与排序_魔术方法解析【教程】  phpstudy本地环境mysql忘记密码_重置mysqlroot密码操作流程【解答】  Win11怎么打开旧版计算器_Win11恢复传统计算器应用【详解】  Windows系统文件被保护机制阻止怎么办_权限不足错误处理方案  mac怎么分屏_MAC双屏显示与分屏操作技巧【指南】  Win11怎么设置虚拟键盘_打开Win11屏幕键盘操作指南【技巧】  如何在 Django 中安全修改用户密码而不使会话失效  Windows10怎么用“讲述人”读屏辅助 Windows10轻松使用开启讲述人朗读屏幕文字帮助视障用户【教程】  Windows7如何安装系统镜像_Windows7系统安装教程【步骤】  php8.4匿名类怎么用_php8.4匿名类创建与使用场景【介绍】  如何在 PHP 单元测试中正确模拟带方法的图像处理门面(Facade)  如何在Golang中捕获结构体方法错误_Golang方法返回error处理实践  Win10怎样设置多显示器_Win10多显示器扩展设置【攻略】  Windows10系统怎么查看显卡驱动_Win10设备管理器驱动更新  Win11怎么设置按流量计费_Win11限制后台流量消耗【网络】  php怎么下载安装并配置环境变量_命令行调用PHP技巧【技巧】  如何使用Golang配置安全开发环境_防止敏感信息泄露  如何在Golang中实现基础配置管理功能_Golang配置文件读取与更新示例  php增删改查报错1054怎么办_字段名错误排查修复【解答】  PythonFastAPI项目实战教程_API接口与异步处理实践  Win11怎么退出微软账户_切换Win11为本地账户登录方法【详解】  如何使用正则表达式提取以编号开头、后接多个注解的逻辑分组块  php订单日志怎么按金额排序_php按订单金额排序日志方法【方法】  mac怎么查看wifi密码_MAC查看已连接WiFi密码方法【技巧】  MAC怎么在照片中添加水印_MAC自带编辑工具文字水印叠加【方法】  Win11怎么设置环境变量_Win11配置Path路径变量【详解】  如何使用Golang table-driven基准测试_多组数据测量函数效率  Windows 10怎么录屏_Windows 10使用Xbox Game Bar录制屏幕视频教程  Win11怎么解压RAR文件 Win11自带解压功能使用方法  PHP cURL GET请求:正确设置请求头与身份认证的完整教程  c++ try_emplace用法_c++ map高效插入数据  Win11怎么设置默认浏览器Chrome_Windows11修改默认网页打开方式  微信里的php文件怎么变mp4_微信接收php转mp4操作步骤【操作】  Win11如何更改用户账户文件夹名称 Win11修改C:Users用户名【终极教程】 

 2026-01-02

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.