Memory Map mmap
mmap 的本质:它将一个文件(Everything is a file,设备亦是如此)的数据,直接映射到进程的虚拟内存地址空间中。进程像读写普通内存一样读写这块内存,内核会自动将这些操作同步到文件或设备上。

#include <sys/mman.h>
void *mmap(size_t length;
void addr[length], size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(size_t length;
void addr[length], size_t length);
addr (起始地址):
- 指定映射区域在进程虚拟地址空间中的期望起始地址。
- 通常 设置为
NULL。设置为NULL表示让操作系统内核自己去选择一个合适的、未被使用的虚拟地址进行映射(这是最推荐和最安全的做法)。如果非要指定,该地址通常需要是页大小(Page Size,通常是 4KB)的整数倍。
length (映射长度):
- 表示要映射的内存区域的大小(以字节为单位)。
- 注意:内核的映射是以页(Page)为单位的,如果你请求的大小不是页的整数倍,内核会自动向上取整到一页的大小,但超出
length的部分虽然会被映射,但访问它可能会导致SIGBUS信号。
prot (内存保护标志):
- 指定映射区域的访问权限,通常由以下几个常量按位或(
|)组合而成:PROT_READ: 映射区域可被读取。PROT_WRITE: 映射区域可被写入。PROT_EXEC: 映射区域可被执行(通常用于动态链接库映射)。PROT_NONE: 映射区域不可访问。
- 注意:指定的权限不能超过文件被打开(
open)时的权限。例如,文件如果是只读打开的,这里就不能包含PROT_WRITE。
flags (映射类型和行为):
- 控制映射对象的更新是否对映射同一对象的其他进程可见,以及更新是否传递到底层文件。必须包含以下两者之一:
MAP_SHARED: 共享映射。对这段内存的修改会同步到底层文件中,并且其他也映射了该文件的进程也能看到这些修改。常用于进程间通信(IPC)。MAP_PRIVATE: 私有映射。采用写时复制(Copy-On-Write)技术。对内存的修改只对当前进程可见,不会同步回底层文件。常用于加载共享库或读取文件内容。
- 常用的其他标志(可按位或):
MAP_ANONYMOUS(或MAP_ANON): 匿名映射。不依赖于任何实际的文件,fd会被忽略(通常设为 -1)。这主要用于像malloc那样分配大块的纯内存(通常大于MMAP_THRESHOLD,比如 128KB)。MAP_FIXED: 强制内核使用addr指定的具体地址,如果该地址不可用则映射失败。极其危险,不建议普通开发使用。
fd (文件描述符):
- 要被映射的文件的文件描述符(由
open()返回)。 - 如果使用了
MAP_ANONYMOUS标志进行匿名映射,则此参数应该设为-1。
offset (文件偏移量):
- 表示从文件的哪个位置开始映射。
- 极其重要的一点:
offset必须是系统页大小(Page Size,可通过sysconf(_SC_PAGE_SIZE)获取,通常为 4096 字节)的整数倍。 - 如果是匿名映射(
MAP_ANONYMOUS),此参数被忽略,通常设为0。