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

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

相关推荐
爱和冰阔落1 小时前
【Linux网络】TCP 半包粘包怎么解决?从长度报头、JSON 拆包到网络计算器完整实战
linux·运维·网络·tcp/ip
汉克老师2 小时前
《从C++小白到算法高手:GESP 1—8级成长地图》第一讲:认识GESP——从编程新手到算法探索者
c++·gesp·信息学竞赛·小学生学c++
say_fall3 小时前
【Linux网络编程】UDP套接字编程:系统编程组件、基础回显服务、InetAddr与地址转换、翻译服务与线程池聊天室
linux·服务器·网络·udp·vr
晴天的雨.9923 小时前
【C++】继承篇
java·开发语言·c++
ö Constancy3 小时前
一台电脑的硬件组成与作用:按功能分类详解(Windows 与 Linux 视角)
linux·windows·电脑
江湖有缘3 小时前
基于Ubuntu部署SoduWork:企业级 AI 原生协同平台实战全流程
linux·人工智能·ubuntu·ai·soduwork
青少儿编程课堂3 小时前
蓝桥杯青少组图形化 + 全国青少年信息素养大赛 + 电子学会图形化考级:校园大富翁经营闯关解析
c++·python·算法·bfs·信息学竞赛
another heaven3 小时前
【C/C++ 第一次跨越(上):用 C++11/14 停止制造新的旧代码】
c语言·c++·制造
qq_406981033 小时前
c++ lamda(三)Lambda表达式
java·前端·c++
无奈笑天下12 小时前
银河麒麟上nproc命令教程详解
linux·运维·服务器