mmap即内存映射技术,其可以将文件映射到程序的内存空间中。而在Linux中,万物皆文件。因此mmap实际上并不只是一个内存映射函数,而是可以将任何在file_operations结构体中提供了 mmap
实现的fd映射到用户空间中。
用户态 mmap
常用的fd来源(或 mmap
能提供的功能)有:
至于 file_operations
中的 mmap
实现,其有如下原理概述:
mmap
本质是将内核管理的一片内存区域映射到用户空间。mmap
后端实现一定是将内核管理的一片内存映射到用户空间中,而无法不使用内核管理的内存。mmap
的函数原型为:
#include <sys/mman.h>
void *mmap(void addr[.length], size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void addr[.length], size_t length);
上述参数中:
addr
:允许用户指定一片内存,若用户不指定则该函数会分配并返回一个地址。length
:用户指定的内存区域大小prot
:用户想要获取的内存权限,包含:
PROT_READ
PROT_WRITE
PROT_EXEC
,如映射JIT编译生成的机器码PROT_NONE
,禁止访问,访问时会触发 SIGSEGV
flags
:
MAP_SHARED
:映射可被多进程共享,对fd的修改MAP_PRIVATE
:对于文件系统,该选项会创建写时复制的副本(或私有映射),随后通过mmap的内存区域对文件的修改不会同步到原文件。对于设备文件,驱动通常不支持。MAP_ANONYMOUS
:映射匿名内存(不需要文件),此时 fd
应设为 -1
,offset
为 0
。MAP_FIXED
:强制使用指定的 addr
,可能覆盖已有映射。MAP_LOCKED
:锁定页面在内存中(避免换出到交换分区,需权限)MAP_POPULATE
:提前预加载映射的物理内存,跳过按需缺页。MAP_NORESERVE
:不预留交换空间,可能导致内存耗尽时触发 OOM
。fd
:需要操作的文件描述符,需要注意:
flags
包含 MAP_ANONYMOUS
时,此时 fd
应设为 -1
。fd
,映射的生命周期与文件描述符无关,关闭fd不影响已映射的内存。offset
:从fd的 offset
处开始映射addr
,除非明确使用 MAP_FIXED
。成功后可使用 *(addr + offset)
操作内存。MAP_FAILED
,并设置 errno
。