mmap更快是因为将文件映射到虚拟内存,读写变为指针操作,省去内核缓冲区拷贝和系统调用开销;但仅适用于大文件(>1MB)、随机访问且页面已加载的场景。

为什么 mmap 比普通 read/write 更快?
因为 mmap 把文件直接映射进进程虚拟内存,读写就变成指针操作,绕过了内核缓冲区拷贝和系统调用开销。但前提是:你真在做**随机访问**,且文件够大(通常 > 1MB)、访问跨度大、不频繁触发缺页异常。
常见错误现象:lseek + read 在小块随机读时反复陷入内核,CPU 花在上下文切换上;而 mmap 后用 *(ptr + offset) 直接取数据,快得多——但仅当页面已加载时成立。
- 不要对小文件(mmap,开销反超
read -
mmap不保证立即加载物理页,首次访问仍会触发缺页中断(软缺页),若文件不在 page cache 中,会变硬缺页(慢) - 必须配合
madvise(..., MADV_RANDOM)或MADV_WILLNEED提示内核,否则预读逻辑可能拖累随机访问性能
如何安全地用 mmap 实现随机读写(C++)
核心不是“怎么映射”,而是“怎么避免崩溃+数据不丢”。关键在标志位、同步时机和地址对齐。
使用场景:日志索引文件、数据库 WAL、固定格式的二进制数据块(如每条记录 512 字节,需按 ID 随机跳转)。
- 读写都用
PROT_READ | PROT_WRITE,映射标志必须含MAP_SHARED(否则修改不落盘) - 起始偏移
offset必须是sysconf(_SC_PAGE_SIZE)的整数倍,否则mmap失败并返回MAP_FAILED - 写完关键数据后,立刻调用
msync(ptr, len, MS_SYNC),别等进程退出——否则断电可能丢最后几页 - 避免用
std::vector包裹mmap返回指针,它会在析构时delete[],导致段错误
示例片段:
int fd = open("data.bin", O_RDWR);
off_t offset = 4096; // 对齐到页
size_t len = 1024 * 1024;
void* ptr = mmap(nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
if (ptr == MAP_FAILED) { /* handle error */ }
// 安全写入第 3 块(假设每块 512B)
char* block3 = static_cast<char>(ptr) + 2 * 512;
memcpy(block3, new_data, 512);
msync(block3, 512, MS_SYNC); // 只刷这一块,更高效</char>
munmap 后还能访问映射内存吗?
不能。一旦调用 munmap,对应地址空间被回收,再读写就是野指针,行为未定义(多数情况直接 SEGFAULT)。
容易踩的坑:
- 把
mmap返回的指针存进类成员,但析构里只关fd没调munmap→ 内存泄漏 + 程序重启后可能映射失败(地址冲突) - 多线程共享同一块映射,一个线程
munmap后其他线程还在用 → 崩溃无警告 - 误以为
close(fd)会自动munmap→ 不会,fd和映射完全解耦
建议封装成 RAII 类,构造映射,析构强制 munmap,且禁止拷贝(只允许移动)。
Windows 上能用 mmap 吗?
不能直接用 mmap,但可用 CreateFileMapping + MapViewOfFile 实现等价功能。接口不同,语义一致。
跨平台陷阱:
- Linux 下
mmap的offset是文件内偏移;Windows 的MapViewOfFile的dwFileOffsetHigh/Low也是文件偏移,但要求 64KB 对齐(而非页对齐),实际仍建议按页对齐以保兼容 - Linux 用
msync刷盘;Windows 用FlushViewOfFile+FlushFileBuffers(后者针对文件句柄,别漏) - 错误码体系完全不同:
mmap失败返回MAP_FAILED;Windows API 返回NULL,需调GetLastError()
如果项目必须跨平台,别手写两套,用 boost::interprocess::mapped_file 或封装一层薄抽象——但要注意它默认不启用 MADV_RANDOM 类似提示,需自行 ioctl 或平台特定调用。
最易被忽略的点:mmap 映射区域的生命周期独立于文件描述符,也独立于文件本身是否被删除。rm 掉文件,只要映射还活着,读写照常;但文件被 truncate,再访问超出原大小的部分会触发 SIGBUS。这事发生前毫无征兆。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











