C++中用mmap映射大文件需先open获取fd并fstat得真实大小,mmap时length须准确、offset页对齐,PROT和MAP标志按读写需求选择,失败检查用MAP_FAILED,访问前校验边界,修改后msync同步,最后munmap释放。

在 C++ 中用 mmap 映射大文件,核心是绕过标准 I/O 缓存,直接让文件内容“变成”进程的虚拟内存,读写就像操作普通指针一样——不拷贝、不阻塞、效率高。
映射文件前先打开并获取大小
必须用 open() 以合适权限打开文件(如 O_RDONLY 或 O_RDWR),再用 fstat() 拿到真实大小。mmap() 的 length 参数不能随便估,必须准确,否则可能映射失败或越界。
- 只读映射推荐用
PROT_READ+MAP_PRIVATE - 需要修改并同步回磁盘,用
PROT_READ | PROT_WRITE+MAP_SHARED -
offset必须是页对齐的(通常getpagesize(),一般为 4096),不足时需向下取整并调整起始地址偏移
调用 mmap 获取映射地址
成功时返回指向映射内存的指针;失败返回 MAP_FAILED(即 (void*)-1),必须检查。不要用 nullptr 判断失败。
示例关键代码:
立即学习“C++免费学习笔记(深入)”;
int fd = open("data.bin", O_RDWR);
struct stat sb;
fstat(fd, &sb);
off_t offset = 0;
size_t length = sb.st_size;
void addr = mmap(nullptr, length, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, offset);
if (addr == MAP_FAILED) {
perror("mmap failed");
close(fd);
return -1;
}
// 此时可直接 reinterpret_cast>(addr)[i] 访问字节
安全访问与边界控制
映射区域虽在虚拟内存中,但访问超出 length 仍会触发 SIGSEGV。尤其处理非对齐 offset 时,实际映射起点可能比文件开头早几个字节,读写前要手动计算有效偏移:
- 若 offset = 1000,页大小=4096,则真实映射起始对应文件 offset 0,映射长度需扩展为 ≥ sb.st_size + 1000
- 业务逻辑中访问位置
pos,应转为指针偏移:static_cast(addr) + (pos - offset) - 建议封装一个 RAII 类,在构造时映射、析构时
munmap+close,避免资源泄漏
修改后同步与解除映射
用 MAP_SHARED 时,修改内存默认不会立即写入磁盘。按需调用:
-
msync(addr, length, MS_SYNC):强制写回并等待完成 -
msync(addr, length, MS_ASYNC):发起写回但不等待 - 最后必须调用
munmap(addr, length),否则内存泄漏;close(fd)可在 munmap 后任意时机调用
不复杂但容易忽略











