跳到主要内容 C++ 共享内存原理及 Windows 实现 | 极客日志
C++
C++ 共享内存原理及 Windows 实现 本文介绍 C++ 在 Windows 平台下使用共享内存进行进程间通信的方法。通过文件映射对象实现多进程访问同一物理内存区域。核心步骤包括创建映射对象、映射到虚拟地址空间、读写数据及释放资源。涉及关键 API 如 CreateFileMapping、OpenFileMapping、MapViewOfFile 等。示例展示了服务端写入和客户端读取的完整流程,适用于高效数据共享场景。
落日余晖 发布于 2026/3/29 更新于 2026/4/13 1 浏览共享内存(Shared Memory)是进程间通信(IPC, Inter-Process Communication)的一种高效方式。
它允许多个进程 直接访问同一块物理内存区域 ,从而实现数据共享,效率远高于管道或消息队列。
一、共享内存原理
在 Windows 系统中,共享内存通过 文件映射对象(File Mapping Object) 实现。
核心思想是:
由一个进程创建一个 命名的内存映射文件 ;
其他进程通过该名称 打开同一个映射对象 ;
通过 MapViewOfFile() 函数把这段共享区域映射到自己进程的虚拟地址空间;
各进程即可读写同一段内存,实现数据共享。
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown 转 HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
HTML 转 Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online
二、服务端程序(创建并写入共享内存)
1. 代码示例 #include <iostream>
#include <Windows.h>
using namespace std;
#define BUF_SIZE 1024
int main () {
char szBuffer[] = "C/C++" ;
HANDLE hMapFile = CreateFileMapping (
INVALID_HANDLE_VALUE,
NULL ,
PAGE_READWRITE,
0 ,
BUF_SIZE,
L"LSEDU"
);
if (hMapFile == NULL ) {
cout << "创建共享内存失败!错误码:" << GetLastError () << endl;
return 0 ;
}
LPVOID lpBase = MapViewOfFile (
hMapFile,
FILE_MAP_ALL_ACCESS,
0 , 0 ,
BUF_SIZE
);
if (lpBase == NULL ) {
cout << "映射内存失败!错误码:" << GetLastError () << endl;
CloseHandle (hMapFile);
return 0 ;
}
strcpy ((char *)lpBase, szBuffer);
cout << "\n服务器程序端:" << (char *)lpBase << endl << endl;
Sleep (20000 );
UnmapViewOfFile (lpBase);
CloseHandle (hMapFile);
return 0 ;
}
2. 输出结果
三、客户端程序(打开并读取共享内存)
1. 代码示例 #include <iostream>
#include <Windows.h>
using namespace std;
#define BUF_SIZE 1024
int main () {
HANDLE hMapFile = OpenFileMapping (
FILE_MAP_ALL_ACCESS,
FALSE,
L"LSEDU"
);
if (hMapFile == NULL ) {
cout << "打开共享内存失败,请检查服务器是否启动。" << endl;
return 0 ;
}
LPVOID lpBase = MapViewOfFile (
hMapFile,
FILE_MAP_ALL_ACCESS,
0 , 0 , BUF_SIZE
);
if (lpBase == NULL ) {
cout << "映射失败!错误码:" << GetLastError () << endl;
CloseHandle (hMapFile);
return 0 ;
}
char szBuffer[BUF_SIZE] = { 0 };
strcpy (szBuffer, (char *)lpBase);
cout << "\n客户端程序端:" << szBuffer << endl << endl;
UnmapViewOfFile (lpBase);
CloseHandle (hMapFile);
return 0 ;
}
2. 输出结果
四、运行步骤
先运行服务器程序(写入端)
创建名为 "LSEDU" 的共享内存区域,并写入字符串数据。
再运行客户端程序(读取端)
客户端打开同名共享内存 "LSEDU",读取其中的数据。
服务端和客户端必须使用相同的共享内存名称;
如果客户端先运行,会提示打开失败;
Sleep(20000) 保证服务端在 20 秒内保持共享内存有效。
五、API 函数说明
1. CreateFileMapping() —— 创建共享内存对象 HANDLE CreateFileMapping (
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCWSTR lpName
) ;
(1)功能
创建一个文件映射对象(File Mapping Object) ,可用于:
将磁盘文件映射到内存;
或者(当 hFile=INVALID_HANDLE_VALUE 时)创建一个基于系统分页文件的共享内存对象 。
参数 说明 hFile需要映射的文件句柄。若为 INVALID_HANDLE_VALUE,表示使用系统分页文件(即纯内存共享) lpAttributes安全属性,一般传 NULL flProtect保护模式,如 PAGE_READWRITE(可读写)、PAGE_READONLY(只读) dwMaximumSizeHigh文件最大尺寸的高 32 位,一般填 0 dwMaximumSizeLow文件最大尺寸的低 32 位,指定共享内存大小(单位:字节) lpName共享内存名称,客户端需使用相同名称打开
(3)返回值
成功:返回文件映射对象句柄(HANDLE)
失败:返回 NULL,可调用 GetLastError() 获取错误代码。
同一名称的映射对象只能创建一次;如果名称已存在,系统返回现有对象句柄。
要确保客户端与服务端的名称一致。
2. OpenFileMapping() —— 打开已存在的共享内存 HANDLE OpenFileMapping (
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCWSTR lpName
) ;
(1)功能
打开由其他进程创建的命名共享内存对象。
参数 说明 dwDesiredAccess打开权限,如 FILE_MAP_ALL_ACCESS(读写)或 FILE_MAP_READ(只读) bInheritHandle是否允许子进程继承句柄,一般为 FALSE lpName共享内存名称,必须与 CreateFileMapping() 中一致
(3)返回值
成功:返回对象句柄
失败:返回 NULL
若共享内存名称错误,或服务端尚未创建对象,则返回 NULL。
打开后需使用 CloseHandle() 关闭。
3. MapViewOfFile() —— 将共享内存映射到当前进程 LPVOID MapViewOfFile (
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap
) ;
(1)功能
将文件映射对象的一部分(或全部)映射到当前进程的虚拟地址空间。
成功后即可直接像操作普通内存一样读写共享内存。
参数 说明 hFileMappingObject文件映射对象句柄(来自 CreateFileMapping 或 OpenFileMapping) dwDesiredAccess访问权限(如 FILE_MAP_ALL_ACCESS) dwFileOffsetHigh / dwFileOffsetLow文件偏移量,一般传 0 dwNumberOfBytesToMap映射大小(字节数),为 0 表示整个文件
(3)返回值
成功:返回指向共享内存首地址的指针(LPVOID)
失败:返回 NULL
返回的是当前进程虚拟空间的地址 ,进程间地址不同但指向相同的物理内存;
必须在使用结束后调用 UnmapViewOfFile() 解除映射。
4. UnmapViewOfFile() —— 解除内存映射 BOOL UnmapViewOfFile (LPCVOID lpBaseAddress) ;
(1)功能
撤销通过 MapViewOfFile() 建立的内存映射关系。
参数 说明 lpBaseAddressMapViewOfFile 返回的映射地址指针
(3)返回值
成功返回 TRUE,失败返回 FALSE。
(4)注意事项
解除映射并不会删除共享内存,只是让当前进程不再访问它。
5. CloseHandle() —— 关闭对象句柄 BOOL CloseHandle (HANDLE hObject) ;
(1)功能
关闭由 CreateFileMapping() 或 OpenFileMapping() 获得的对象句柄。
参数 说明 hObject对象句柄,如共享内存、文件、线程等
(3)返回值
成功返回 TRUE,失败返回 FALSE。
调用此函数不会立即销毁共享内存,只有所有进程都关闭后 系统才会释放资源。
6. Sleep() —— 线程休眠 void Sleep (DWORD dwMilliseconds) ;
(1)功能
使当前线程挂起指定时间(单位:毫秒)。
参数 说明 dwMilliseconds挂起时间,如 Sleep(20000) 表示休眠 20 秒
(3)作用
用于让服务器程序保持共享内存有效时间,等待客户端读取。
7. GetLastError() —— 获取系统错误码 DWORD GetLastError (void ) ;
功能:当某个 Windows API 调用失败时,用此函数可获得错误代码。
通常可以配合 FormatMessage() 打印详细错误说明。
8. API 函数小结 函数名 类型 主要作用 CreateFileMappingWindows API 创建共享内存对象 OpenFileMappingWindows API 打开已有共享内存对象 MapViewOfFileWindows API 建立映射关系(映射到本进程) UnmapViewOfFileWindows API 解除映射 CloseHandleWindows API 关闭句柄 SleepWindows API 延时等待 GetLastErrorWindows API 获取系统错误信息
六、总结 分类 描述 技术名称 共享内存(Shared Memory) 实现原理 基于文件映射(File Mapping) 优点 速度快,数据直接共享,无需拷贝 缺点 需额外同步机制(如信号量、互斥量)保证数据一致性 应用场景 进程间数据共享、图像传输、IPC 通信等