mmap的使用与底层原理

mmap(Memory Map,内存映射)是一种将文件或其它对象映射到进程虚拟地址空间的方法。通过 mmap,程序可以把文件的某一部分当作连续的内存来直接读写,而不需要再调用传统的 readwrite 等 I/O 系统调用。

使用

mmap的函数签名如下:

cpp 复制代码
void* mmap(
    void* addr,
    size_t length,
    int prot,
    int flags,
    int fd,
    off_t offset
);

六个参数分别是

txt 复制代码
addr    希望映射到哪个虚拟地址,一般传 nullptr
length  映射多少字节
prot    这块内存允许你做什么:读 / 写 / 执行
flags   这块映射怎么和文件交互:私有 / 共享 等
fd      文件描述符
offset  从文件哪个位置开始映射

重点讲讲protflag的区别

prot控制内对这块内存做什么,常见值包括PROT_READ、PROT_WRITE、PROT_EXEC、PROT_NONE

分别控制可以对返回的void*进行什么类型的操作,读/写/可执行/什么都不允许

flags控制内存与文件的映射关系MAP_PRIVATE、MAP_SHARED、MAP_ANONYMOUS

比如private,表示对内存的修改不会映射到文件,相当于是私有的,shared则是对内存的修改会映射到文件,别的进程也可以看见。当参数是MAP_ANONYMOUS时,表示不需要文件进行映射,这个一般用于父子进程之间本来就有一份进程地址空间的拷贝。

offset一般时page_size的倍数

原理

mmap 不是"把文件读进内存",而是"在进程虚拟地址空间里建立一段映射关系,让这段虚拟地址背后对应文件页或匿名内存页"

mmap 干的事情,本质就是操作虚拟地址与物理页的映射关系。

read的一个直观的对比如下

cpp 复制代码
char buffer[4096];
read(fd, buffer, 4096); //这里经历了一次拷贝从文件->page cache到用户态buffer的拷贝

void* p = mmap(...);//这里没经历拷贝就建立了映射关系
p[offset]; //读写时发生缺页中断,按需加载,少一次到用户态的拷贝

所以mmap一开始只是建立一个映射,并不会立马加载数据

prot = prot_shared时,便是两个进程的虚拟地址映射到同一个物理页,写时标记该页为脏页,之后会修改文件,同样也可以主动调用::msync(...)落盘,

prot = prot_priate时,进程正常读没有问题,写时会触发写时复制,讲物理页复制到一个新的匿名页,并在其上做对应的修改,于是其他映射到物理页的进程看不到修改

prot = MAP_ANONYMOUS | MAP_SHARED时,可以和fork配合,先mmap,简历映射,再fork,此时子进程把父进程的虚拟地址空间布局 继承过去且由于是share模式,此时虽然是匿名页,且父子进程虽然是两个不同的进程,且有自己的页表,但这两个页表项可以指向同一个物理页

以上是我个人一些浅显的理解,以后再补充吧

相关推荐
GeW几秒前
RHCE10一次过!提高通过率+快速拿证的7个核心技巧
linux
莫生灬灬8 分钟前
灵码 LingBuilder:用中文写代码,确定性生成真实 C++ 工程(开源)
c++·开源·mfc
浅念-9 分钟前
C++ Protobuf 入门实战:基于通讯录项目吃透proto3语法与序列化
linux·服务器·网络·c++·protobuf·proto·proto3
不怕犯错,就怕不做35 分钟前
RK linux在buildroot中如何添加linux命令
linux·驱动开发·嵌入式硬件
小羊在睡觉44 分钟前
HLS视频
linux·后端·golang
宵时待雨1 小时前
linux笔记归纳18:传输层协议TCP
linux·网络·笔记·网络协议·tcp/ip
吴声子夜歌1 小时前
Shell编程——条件测试与比较
linux·运维·shell
音草1 小时前
Linux 基础指令入门:常用命令、Shell 原理与权限管理
linux
aosky1 小时前
Linux 写内容到文件的几种方式
java·linux·服务器
汉克老师2 小时前
CSP-J 初赛(以满分为目标):第三十九课《数学与逻辑②——阶乘、排列数与组合数:公式到底从哪里来?》
c++·csp-j·小学生·学c++编程