mmap
(Memory-mapped Files,内存映射文件)是 Linux/Unix 系统提供的一种将文件直接映射到进程虚拟地址空间的机制。通过 mmap
,文件可以像访问内存一样被读写,避免了传统的 read/write
系统调用和用户态缓冲区的拷贝,从而提高 I/O 性能。以下是关键点解析:
1. 核心原理
- 映射过程:
调用mmap
后,内核将文件的某一部分(或全部)映射到进程的虚拟地址空间。此时并未实际加载文件数据到物理内存,而是建立虚拟内存到文件的关联。 - 按需加载:
当进程访问映射区域的某个地址时,触发缺页中断(Page Fault),内核才将对应的文件内容加载到物理内存(惰性加载)。
2. API 函数
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
- 参数说明:
addr
:建议的映射起始地址(通常设为NULL
,由内核决定)。length
:映射长度。prot
:保护模式(如PROT_READ | PROT_WRITE
)。flags
:控制映射行为(如MAP_SHARED
、MAP_PRIVATE
)。fd
:文件描述符。offset
:文件偏移量(需按页大小对齐)。
3. 典型应用场景
(1) 高性能文件 I/O
- 优势:避免用户态与内核态的数据拷贝,适合大文件频繁读写(如数据库、日志处理)。
- 示例:
int fd = open("data.bin", O_RDWR); void *ptr = mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); // 直接通过 ptr[index] 访问文件内容
(2) IPC(进程间通信)
- 共享匿名映射:
通过MAP_ANONYMOUS | MAP_SHARED
,父子进程共享同一块内存区域。 - 示例:
void *shared_mem = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_SHARED, -1,0);
if (fork() ==0){
//子进程修改 shared_mem
}else{
//父进程读取 shared_mem
}
(3) Zero-Copy网络传输
- 结合 sendfile/DMA:
将磁盘文件直接映射到内存,再通过网络接口发送,减少 CPU 参与。
4. mmap vs read/write
特性 | mmap | read/write |
---|---|---|
数据拷贝次数 | 0次(直接操作内存) | 2次(内核↔用户缓冲区) |
大文件性能 | 更高(避免频繁系统调用) | 较低 |
小文件开销 | 可能较高(缺页中断成本) | 更轻量 |
随机访问支持度 | 天然支持 | 需 lseek |
5.注意事项
- 对齐要求: offset必须是4096倍数(通常等于系统页大小) -资源释放:使用munmap()解除映射并关闭fd.
munmap(ptr,len); close(fd);
-同步写入:msync()确保修改回写到磁盘.
如果需要深入某个方向(如性能优化陷阱或具体代码案例),可以进一步探讨!
内容由零声教学AI助手提供,问题来源于学员提问