Linux用mmap、Windows用CreateFileMapping+MapViewOfFile,二者语义相近但接口差异大,混用会崩溃或读写错位;需严格匹配打开模式与保护标志、注意大小对齐、映射刷新及生命周期管理。

Linux 用 mmap,Windows 用 CreateFileMapping + MapViewOfFile,二者语义接近但接口差异大,混用或照搬示例会直接崩溃或读写错位。
Linux 下 mmap 必须检查 MAP_SHARED 与 MAP_PRIVATE 的行为区别
多数人默认用 MAP_SHARED,但若只读不写、或需避免脏页回写到磁盘(比如解析只读资源包),MAP_PRIVATE 更安全。错误用法是:打开文件只读却传 PROT_WRITE,mmap 直接返回 MAP_FAILED;或没调 open() 时加 O_RDWR 就尝试写入,触发 SIGBUS。
- 映射前确保
open()的 flag 和prot参数匹配:O_RDONLY→PROT_READ;O_RDWR→PROT_READ | PROT_WRITE - 写入后如需立即落盘,必须调
msync(addr, len, MS_SYNC);仅MAP_SHARED有效,MAP_PRIVATE调用无效且返回 -1 - 映射长度不能超过文件当前大小(
lseek(fd, 0, SEEK_END)获取),否则访问越界段会触发SEGV_MAPERR
Windows 下 CreateFileMapping 的 dwMaximumSizeHigh/dwMaximumSizeLow 容易被忽略高位
32 位程序在 Windows 上处理大于 4GB 的文件时,dwMaximumSizeLow 单独赋值会截断高位,导致映射视图为空或访问异常。常见错误是直接把 size_t 强转成 DWORD 传给 dwMaximumSizeLow,而没拆分高低 32 位。
- 正确做法:
dwMaximumSizeLow = (DWORD)file_size,dwMaximumSizeHigh = (DWORD)(file_size >> 32) -
CreateFileMapping返回INVALID_HANDLE_VALUE时,必须用GetLastError()判断具体原因:权限不足(ERROR_ACCESS_DENIED)、文件已锁定(ERROR_SHARING_VIOLATION)、或内存不足(ERROR_NOT_ENOUGH_MEMORY) -
MapViewOfFile的dwNumberOfBytesToMap可小于文件大小,但起始偏移必须是系统分配粒度(GetSystemInfo().dwAllocationGranularity)的整数倍,否则失败
跨平台读写一致性:文件大小变更与映射刷新问题
映射建立后,Linux 下文件被 truncate 或 extend,已映射区域不会自动更新——mmap 视图仍按原大小生效;Windows 下同理,CreateFileMapping 创建时指定的大小即为上限,后续扩大文件不会扩展映射视图。强行访问新增区域会触发段错误或访问违规。
- 需要动态扩容时,Linux 必须
munmap+ 重新open+mmap;Windows 需UnmapViewOfFile+CloseHandle+ 重建映射 - 多进程同时映射同一文件时,Linux 下
MAP_SHARED支持自动同步,Windows 下需确保所有映射都使用FILE_MAP_WRITE权限,且写入后调FlushViewOfFile(等效于msync) - 不要依赖
stat()/GetFileSize获取“当前”大小来判断映射是否有效——它反映的是文件系统状态,不是映射视图边界
真正麻烦的不是首次映射,而是映射生命周期管理:谁负责 munmap / UnmapViewOfFile,何时释放底层 fd / hFile,以及多线程下映射地址是否可重入——这些细节一旦错位,轻则数据丢失,重则进程静默崩溃。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











