mmap的使用与底层原理

mmap(Memory Map,内存映射)是一种将文件或其它对象映射到进程虚拟地址空间的方法。通过 mmap,程序可以把文件的某一部分当作连续的内存来直接读写,而不需要再调用传统的 read 或 write 等 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  从文件哪个位置开始映射

重点讲讲prot和flag的区别

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模式,此时虽然是匿名页,且父子进程虽然是两个不同的进程,且有自己的页表,但这两个页表项可以指向同一个物理页。

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

相关推荐
爱好曙光5 分钟前
生产延迟尖刺排查:用 bpftrace 抓系统调用与调度延迟
linux·ebpf·延迟·性能排查·bpftrace
INGNIGHT22 分钟前
377.组合总和 Ⅳ(背包)
c++·算法·1024程序员节
Ruiery33 分钟前
Linux 6.6内核并发与同步(一):原子操作与内存屏障 — 内核同步的硬件底座
linux·运维·服务器·1024程序员节
码完就睡35 分钟前
Linux——IP协议与路由选择
linux·网络·tcp/ip·1024程序员节
H.莓飛35 分钟前
【数据结构】排序_OJ题(二):划分与选择
linux·服务器·c语言·开发语言·数据结构·visual studio
艸肅42 分钟前
Docker 国内镜像源配置
linux·ubuntu·docker·1024程序员节
猿粪已尽42 分钟前
mac 中 iTerm2 使用 rz、sz 上传下载文件详解,附 scp 操作指南
linux·macos·scp·lrzsz
宁波阿成1 小时前
CentOS 7.5 升级 PHP 至 8.3.36 完整实操记录
linux·centos·php
djjjx.1 小时前
Linux进程篇(七):环境变量的底层溯源、核心获取机制与安全应用
linux·运维·服务器
凉茶钱1 小时前
stack、queue、priority_queue、容器适配器完整梳理
开发语言·c++·queue·1024程序员节·stack