0

0

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

尼克

尼克

发布时间:2026-01-02 17:48:08

|

917人浏览过

|

来源于php中文网

原创

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

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

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 截断导致权限不足。

立即学习C++免费学习笔记(深入)”;

  • 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)),避免不同编译器填充差异导致读写错位

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

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

312

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

229

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

434

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

250

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

205

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1436

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

609

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

547

2024.03.22

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

74

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.4万人学习

Git 教程
Git 教程

共21课时 | 2.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号