深入理解MMAP原理,让大厂都爱不释手的技术


作者:android阿牛
链接:https://www.jianshu.com/p/0cf8eff07f5e

如微信的MMKV 组件、美团的Logan组件,还有微信的日志模块xlog,为什么大厂偏爱它呢?他到底有什么魔力么?我认为主要原因如下:

  • 跨平台,C++编写,可以支持多平台

  • 跨进程,通过文件共享可以实现多个进程内存共享,实现进程通信

  • 高性能,实现用户空间和内核空间的零拷贝,速度快且节约内存等

  • 高稳定,页中断保护神,由操作系统实现的,稳定性可想而知

函数介绍

voidmmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);
  • addr 代表映射的虚拟内存起始地址;

  • length 代表该映射长度;

  • prot 描述了这块新的内存区域的访问权限;

  • flags 描述了该映射的类型;

  • fd 代表文件描述符;

  • offset 代表文件内的偏移值。

  • 微信搜索公众号:Linux技术迷,回复:linux 领取资料 。

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原理,让大厂都爱不释手的技术

一个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(nullptr4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -10);

    if (c_pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (c_pid > 0) {
        printf("parent process pid: %dn", getpid());
        sprintf(shm, "%s""hello, my child");
        printf("parent process got a message: %sn", shm);
        wait(nullptr);
    } else {
        printf("child process pid: %dn", getpid());
        sprintf(shm, "%s""hello, father.");
        printf("child process got a message: %sn", 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传入-1MAP_ANONYMOUS配置实现匿名映射,使用MAP_SHARED创建共享区域,使用fork函数创建子进程,这样来实现子进程通信,通过sprintf将格式化后的数据写入到共享内存中。

通过简单的几行代码就实现了跨进程通信,如此简单,这么强大的东西,背后有什么支撑么?带着问题我们接着一探究竟。

MMAP背后的保护神

说到MMAP的保护神,首页了解下内存页:在页式虚拟存储器中,会在虚拟存储空间和物理主存空间都分割为一个个固定大小的页,为线程分配内存是也是以页为单位。比如:页的大小为 4K,那么 4GB 存储空间就需要4GB/4KB=1M 条记录,即有 100 多万个 4KB 的页,内存页中,当用户发生文件读写时,内核会申请一个内存页与文件进行读写操作,如图:

深入理解MMAP原理,让大厂都爱不释手的技术

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

四种场景分配原理

深入理解MMAP原理,让大厂都爱不释手的技术

上面是一个简单的原理总结,并没有详细的展开,感兴趣可以自己查查资料哈。

总结

本次分享,主要介绍了mmap的四种应用场景,通过一个实例验证了父子进程间的通信,并深入mmap找到它的保护神,且深入了解到mmap在四种场景下,操作系统是如何组织分配,通过对这些的了解,在你之后的mmap实战应用有了更好的理论基础,可以根据不同的需求,不同的性能要求等,选择最合适的实现。

--完--

读到这里说明你喜欢本公众号的文章,欢迎 置顶(标星)本公众号 架构师指南,这样就可以第一时间获取推送了~

本公众号 架构师指南,后台回复:架构师,领取2T学习资料 !
1. 后端架构师技术大全(69个点)
2. 架构师如何设计权限系统?
3. 我怎么才能成为一个架构师 ?
4. 架构师从0搭建一套订单系统!

深入理解MMAP原理,让大厂都爱不释手的技术

深入理解MMAP原理,让大厂都爱不释手的技术

本篇文章来源于微信公众号:程序IT圈

原创文章,作者:software,如若转载,请注明出处:https://www.sldh123.com/6662.html

(0)
上一篇 11月 25, 2022 3:45 上午
下一篇 11月 25, 2022 3:45 上午

相关推荐

  • 快速了解 Kubernetes 的架构及特性

    因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享 kubernetes 已经成为容器编排领域的王者,它是基于容器的集群编排引擎,具备扩展集群、滚动升级回滚、弹…

    10月 15, 2022
    770
  • 我怎么才能成为一个架构师 ?

    “我怎么才能成为一个软件架构师?” 这是很多小伙伴问我的一个问题,最近看到Kai Niklas讲架构师的一篇文章,其中的真知灼见引起了我的强烈共鸣,尤其是后面的非技术部分。翻译过来…

    10月 27, 2022
    710
  • 多图深入理解 Redis

    因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享 什么是 Redis? Redis(REmote DIctionary Service)是一个开源的键值对数据…

    1月 5, 2023
    600
  • 架构师细谈八种架构设计模式及其优缺点

    什么是架构 我想这个问题,十个人回答得有十一个答案,因为另外的那一个是大家妥协的结果。哈哈,我理解,架构就是骨架,如下图所示: 人类的身体的支撑是主要由骨架来承担的,然后是其上的肌…

    8月 3, 2022
    810
  • 2万字,我们谈谈分布式事务

    分布式事务 1 基础概念 1.1 什么是事务 什么是事务?举个生活中的例子:你去小卖铺买东西,“一手交钱,一手交货”就是一个事务的例子,交钱和交货必 须全部成功,事务才算成功,任一…

    12月 30, 2022
    470
  • 分布式 ID 生成方案总结整理

    1. 为什么需要分布式 ID 对于单体系统来说,主键 ID 常用主键自动的方式进行设置。这种 ID 生成方法在单体项目是可行的,但是对于分布式系统,分库分表之后就不适应了。比如订单…

    2月 2, 2023
    260
  • 架构师谈谈软件开发模式:瀑布与敏捷

    瀑布和敏捷不是什么新概念,这里只是个人在团队合作中不得不去思考而做的归纳和总结,同时记录自己曾经踩过的坑,新瓶装旧酒,希望对你有所启发。 瀑布模式   瀑布模型是比较传统一种开发模…

    11月 25, 2022
    670
  • 推荐全网最好的开源压缩软件,没有之一!

    7-Zip 是一款拥有极高压缩比的开源压缩软件。 许可协议 7-Zip 是一款 开源 软件。大多数源代码都基于 GNU LGPL 许可协议下发布。AES 代码基于 BSD 许可下发…

    11月 16, 2022
    1490
  • 架构师学习使用队列解耦的架构方案

    原文:www.cnblogs.com/bossma/p/mq-decouple-architecture.html 作者:波斯码    搞技术的对“高内聚,低耦…

    9月 23, 2022
    770
  • 架构师谈流程引擎的架构设计

    1 什么是流程引擎 流程引擎是一个底层支撑平台,是为提供流程处理而开发设计的。流程引擎和流程应用,以及应用程序的关系如下图所示。 常见的支撑场景有:Workflow、BPM、流程编…

    12月 10, 2022
    660

发表回复

您的电子邮箱地址不会被公开。