当前位置:网站首页>深入理解MMAP原理,让大厂都爱不释手的技术
深入理解MMAP原理,让大厂都爱不释手的技术
2022-07-29 05:21:00 【代码与思维】
如微信的MMKV 组件、美团的Logan组件,还有微信的日志模块xlog,为什么大厂偏爱它呢?他到底有什么魔力么?我认为主要原因如下:
- 跨平台,C++编写,可以支持多平台
- 跨进程,通过文件共享可以实现多个进程内存共享,实现进程通信
- 高性能,实现用户空间和内核空间的零拷贝,速度快且节约内存等
- 高稳定,页中断保护神,由操作系统实现的,稳定性可想而知
函数介绍
void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);
- addr 代表映射的虚拟内存起始地址;
- length 代表该映射长度;
- prot 描述了这块新的内存区域的访问权限;
- flags 描述了该映射的类型;
- fd 代表文件描述符;
- offset 代表文件内的偏移值。
mmap的强大之处在于,它可以根据参数配置,用于创建共享内存,从而提高文件映射区域的IO效率,实现IO零拷贝,后面讲下零拷贝的技术,对比下,决定这些功能的主要就是三个参数,下面一一解释
prot
四种情况如下:
- PROT_EXEC,代表该内存映射有可执行权限,可以看成是代码段,通常存储CPU可执行机器码
- PROT_READ,代表该内存映射可读
- PROT_WRITE,代表该内存映射可写
- PROT_NONE,代表该内存映射不能被访问
flags
比较有代表性的如下:
- MAP_SHARED,创建一个共享映射区域
- MAP_PRIVATE,创建一个私有映射区域
- MAP_ANONYMOUS,创建一个匿名映射区域,该情况只需要传入-1即可
- MAP_FIXED,当操作系统以addr为起始地址进行内存映射时,如果发现不能满足长度或者权限要求时,将映射失败,如果非MAP_FIXED,则系统就会再找其他合适的区域进行映射
fd
当参数fd不等于0时,内存映射将与文件进行关联,如果等于0,就会变成匿名映射,此时flags必为MAP_ANONYMOUS
应用场景

一个mmap竟有如此丰富的功能,从申请分配内存到加载动态库,再到进程间通信,真的是无所不能,强大到让人五体投地。下面就着四种情况,拿一个我最关心的父子进程通信来举例看下,实现一个简单的父子进程通信逻辑,毕竟我们学习的目的就是为了应用,光有理论怎么能称之为合格的博客呢?
父子进程共享内存
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/mman.h>
int main() {
pid_t c_pid = fork();
char* shm = (char*)mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (c_pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (c_pid > 0) {
printf("parent process pid: %d\n", getpid());
sprintf(shm, "%s", "hello, my child");
printf("parent process got a message: %s\n", shm);
wait(nullptr);
} else {
printf("child process pid: %d\n", getpid());
sprintf(shm, "%s", "hello, father.");
printf("child process got a message: %s\n", shm);
exit(EXIT_SUCCESS);
}
return EXIT_SUCCESS;
}
运行后打印如下
parent process pid: 87799
parent process got a message: hello, my child
child process pid: 87800
child process got a message: hello, father.
Process finished with exit code 0
用mmap创建了一块匿名共享内存区域,fd传入**-1和MAP_ANONYMOUS配置实现匿名映射,使用MAP_SHARED**创建共享区域,使用fork函数创建子进程,这样来实现子进程通信,通过sprintf将格式化后的数据写入到共享内存中。
通过简单的几行代码就实现了跨进程通信,如此简单,这么强大的东西,背后有什么支撑么?带着问题我们接着一探究竟。
MMAP背后的保护神
说到MMAP的保护神,首页了解下内存页:在页式虚拟存储器中,会在虚拟存储空间和物理主存空间都分割为一个个固定大小的页,为线程分配内存是也是以页为单位。比如:页的大小为 4K,那么 4GB 存储空间就需要4GB/4KB=1M 条记录,即有 100 多万个 4KB 的页,内存页中,当用户发生文件读写时,内核会申请一个内存页与文件进行读写操作,如图:

这时如果内存页中没有数据,就会发生一种中断机制,它就叫缺页中断,此中断就是MMAP的保护神,为什么这么说呢?我们知道mmap函数调用后,在分配时只是建立了进程虚拟地址空间,并没有分配虚拟内存对应的物理内存,当访问这些没有建立映射关系的虚拟内存时,CPU加载指令发现代码段是缺失的,就触发了缺页中断,中断后,内核通过检查虚拟地址的所在区域,发现存在内存映射,就可以通过虚拟内存地址计算文件偏移,定位到内存所缺的页对应的文件的页,由内核启动磁盘IO,将对应的页从磁盘加载到内存中。最终保护mmap能顺利进行,无私奉献。了解完缺页中断,我们再来细聊下mmap四种场景下的内存分配原理
四种场景分配原理

上面是一个简单的原理总结,并没有详细的展开,感兴趣可以自己查查资料哈。
总结
本次分享,主要介绍了mmap的四种应用场景,通过一个实例验证了父子进程间的通信,并深入mmap找到它的保护神,且深入了解到mmap在四种场景下,操作系统是如何组织分配,通过对这些的了解,在你之后的mmap实战应用有了更好的理论基础,可以根据不同的需求,不同的性能要求等,选择最合适的实现。
作者:i校长
链接:https://juejin.cn/post/7119116943256190990
边栏推荐
- 华为2020校招笔试编程题 看这篇就够了(上)
- Training log 6 of the project "construction of Shandong University mobile Internet development technology teaching website"
- Plato farm is expected to further expand its ecosystem through elephant swap
- Strategic cooperation with many institutions shows the strength of the leading company of platofarm yuancosmos
- “山东大学移动互联网开发技术教学网站建设”项目实训日志一
- 在uni-app项目中,如何实现微信小程序openid的获取
- Rsync+inotyfy realize real-time synchronization of single data monitoring
- 中海油集团,桌面云&网盘存储系统应用案例
- How to make interesting apps for deep learning with zero code (suitable for novices)
- IDEA中设置自动build-改动代码,不用重启工程,刷新页面即可
猜你喜欢

Markdown syntax

完全去中心化的编程模式,不需要服务器,也不需要ip,就像一张漫无目的的网络、四处延伸

微信小程序源码获取(附工具的下载)

mysql 的show profiles 使用。

Machine learning makes character recognition easier: kotlin+mvvm+ Huawei ml Kit

赓续新征程,共驭智存储

一文读懂Move2Earn项目——MOVE

Move protocol global health declaration, carry out the health campaign to the end

Super simple integration HMS ml kit face detection to achieve cute stickers

Dao race track is booming. What are the advantages of m-dao?
随机推荐
量化开发必掌握的30个知识点【什么是Level-2数据】
加密资产熊市之下,PlatoFarm的策略玩法依旧能获得稳定收益
DataX installation
Detailed explanation of atomic operation class atomicinteger in learning notes of concurrent programming
Study and research the way of programming
Android Studio 实现登录注册-源代码 (连接MySql数据库)
Madonna "hellent" bought $1.3 million NFT boring ape, which is now considered too expensive
深度学习的趣味app简单优化(适合新手)
mysql在查询字符串类型的时候带单引号和不带的区别和原因
Refresh, swagger UI theme changes
突破硬件瓶颈(一):Intel体系架构的发展与瓶颈挖掘
30 knowledge points that must be mastered in quantitative development [what is individual data]?
How can Plato obtain premium income through elephant swap in a bear market?
XDFS&空天院HPC集群典型案例
C# 判断用户是手机访问还是电脑访问
PHP write a diaper to buy the lowest price in the whole network
华为2020校招笔试编程题 看这篇就够了(上)
Tear the ORM framework by hand (generic + annotation + reflection)
“山东大学移动互联网开发技术教学网站建设”项目实训日志四
Crypto giants all in metauniverse, and platofarm may break through