深入理解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)
上一篇 1天前
下一篇 1天前

相关推荐

  • CPU模型,内存分页与调优,内核与用户空间

    作者:景宗会链接:https://www.jianshu.com/p/c1fd3b0a0f2a 1 CPU模型 去过机房的同学都知道,一般在大型服务器上会配置多个CPU,每个CPU…

    9月 13, 2022
    250
  • Netty 如何做到单机百万并发?

    相信很多人知道石中剑这个典故,在此典故中,天命注定的亚瑟很容易的就拔出了这把石中剑,但是由于资历不被其他人认可,所以他颇费了一番周折才成为了真正意义上的英格兰全境之王,亚瑟王。 说…

    10月 27, 2022
    240
  • 基于Spring Cloud的微服务架构分析

    Spring Cloud是一个相对比较新的微服务框架,2016年才推出1.0的release版本. 虽然Spring Cloud时间最短, 但是相比Dubbo等RPC框架, Spr…

    7月 18, 2022
    140
  • 架构师必须清楚的支付系统:对账系统详解

    在支付系统中,资金对账在对账中心进行,将系统保存的账务流水与银行返回的清算流水和清算文件进行对账,核对系统账务数据与银行清算数据的一致性,保证支付机构各备付金银行账户每日的预计发生…

    7月 3, 2022
    220
  • 超1.5万台Kafka,每秒数亿消息量的挑战

    因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享 Kafka在美团数据平台承担着统一的数据缓存和分发的角色,随着数据量的增长,集群规模的扩大,Kafka面临的…

    10月 27, 2022
    210
  • Netty 实现百万连接的难点和优化点

    推送服务 还记得一年半前,做的一个项目需要用到 Android 推送服务。和 iOS 不同,Android 生态中没有统一的推送服务。Google 虽然有 Google Cloud…

    8月 24, 2022
    310
  • 架构师谈系统架构性能优化思路

    今天谈下业务系统性能问题分析诊断和性能优化方面的内容。这篇文章重点还是谈已经上线的业务系统后续出现性能问题后的问题诊断和优化重点。 系统性能问题分析流程 我们首先来分析下如果一个业…

    9月 24, 2022
    200
  • 架构师聊聊分布式定时任务框架选型

    我们先思考下面几个业务场景的解决方案: 支付系统每天凌晨1点跑批,进行一天清算,每月1号进行上个月清算 电商整点抢购,商品价格8点整开始优惠 12306购票系统,超过30分钟没有成…

    8月 7, 2022
    230
  • 架构师如何统一公司的产品登录互通?

    因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享 目录 简介 传统 Session 机制及身份认证方案 集群环境下的 Session 困境及解决方案 多服务下…

    10月 15, 2022
    280
  • 架构概述之架构演化、模式与核心要素

    如何打造一个高可用、高性能、易扩展、可伸缩且安全的应用系统?相信这是困扰着无数开发者的难题,在这里我们以一个网站为例,来讨论一下如何做好大型应用系统的架构设计。 架构演化发展历程 …

    9月 25, 2022
    180

发表回复

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