奇技指南

作者说:最近在工作中遇到一个mmap使用相关的问题,造成了一定的困惑,于是花了些时间补了下 mmap的功课,在这里分享给大家,错误和不足之处大家多指教。

相关背景知识

  • 说到mmap的使用,我们首先要了解一下进程的虚拟进程地址空间的概念。Linux上为了作进程隔离,每个进程都运行在自己的单独的虚拟进程空间,同时物理机上内存有限,每个进程使用虚拟内存地址来隔离又共享物理内存。我们平时在代码里获取的地址就是虚拟地址;
  • 放一张进程虚拟地址空间草图,网上也可以很容易找到更精美的
  • 我们在程序中申请内存的操作,实际上只是在进程地址空间相应部分申请了一段虚拟地址,当实际对这段虚拟地址进行读写操作时,才会分配真正的物理内存;
  • 通常x86 Linux采用段页式的内存管理模式,这块不具体展开,简单来说就是CPU访问的逻辑地址,然后经过分段机制转换成线性地址(你可以简单理解成等价于上面说的虚拟地址),再经过分页机制转换成物理地址,第一次访问的时候由于实现物理地址还没有分配,会产生缺页中断来分配物理地址,用它来填充对应的页表项;
  • 通过read系统调用来读取磁盘上的文件时,文件内容会先被读到内存的page cache部分,然后再从page cache中拷贝到应用层的读缓存buffer中;对于打开的文件,内核都会在内存中维护一个inode结构体(对于同一个文件,即使被open多次,内核也仅维护这一个inode),其有一个成员是struct address_space*i_mapping , 它用来维护这个文件被读取的所有部分在内存中的缓存,其使用xarray(全新封装了基数树的操作)来存储这个物理页(struct page), 如下图:

mmap简介

  • 先看原型:void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
  • 功能
  1. 分配一块新的连续的进程虚拟地址段(对应内核中的结构体就是 vm_area_struct)并返回其起始地址,如果给定了第一个参数,就优先从这个地址开始分配进程虚拟地址;
  2. 如果提供了fd文件句枘,则映射文件内容到进程虚拟地址;
  3. mmap的参数较多,其中prot和flags的可选项也比较多,具体大家可以使用 man命令查看;

mmap的几种典型应用

  • 不同进程(可以是非父子进程)间共享映射
  1. 这种情况需要借助磁盘文件,实际上是共享这个磁盘文件,将这个磁盘文件映射到各自的进程虚拟地址空间,但是其虚拟地址空间分页转换后其页表项对应的物理内存是相同的;
  2. 典型用法是需提供一个打开的文件句柄,使用 MAP_SHARED flag
int fd = open ("[filepath]", O_RDWR))void *addr = mmap (NULL, [mmaping length], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
  • 非子进程间通讯
  1. 父进程使用 fork创建子进程,父子进程间可以使用mmap来通读;
  2. 典型用法是无需提供打开的文件句柄, 使用 MAP_SHARED | MAP_ANONYMOUS flag,
void *addr = mmap (NULL, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  • 进程通过 mmap 来读写文件
  1. 从上面 相关背景知识 一节可知使用 read系统调用读文件时,数据需经过 磁盘拷贝到page cache, page cache再拷贝到应用层缓存bufffer, 这两个数据拷贝;
  2. 使用 mmap 时,磁盘数据也是先读到page cache中,然后会将mmap返回的虚拟地址最终对应的页项表内容设定为和前面的page chache相同的物理页, 这样一来就免去了第二次的数据拷贝;
  3. 用个示意图来说明一下:
  • 用作glibc中malloc申请内存
  1. 通常我们都说是通过调用 malloc来申请堆上内存,但实际上其内部实现使用了 brk和 mmap两种系统调用,当申请的内存大于128K时,使用 mmap
  2. 典型用法是无需提供打开的文件句柄, 使用 MAP_PRIVATE | MAP_ANONYMOUS flag
void *addr = mmap (NULL, buffer_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  • mmap的写时拷贝
  1. 如果我们在调用mmap时提供一个打开的文件句两,但使用 MAP_PRIVATE的flags, 那这时对其的写操作并不能真正修改对应的磁盘文件,它会作写时拷贝,退化成匿名映射

mmap作磁盘文件映射时的特别说明

  • mmap映射的虚拟地址长度(即mmap的第二个参数)需要对齐到物理页大小,在32位系统上通常是4K, 这一特点会导致一些有趣的事情发生,我们来看一下:假如一个文件的大小是5000Byte, 刚好比4K大一些,我们用mmap来从文件开始的位置来映射它,mmap的第二个参数给5000, 因为需要页面对齐,实现映射的虚拟地址长度将是两个4k,即8192, 8192 - 5000 = 3192的部分用0填充,也是可以被访问到;
  • 如果用mmap映射某个文件时,这个文件大小为0, 不会分配任何的物理内存,也不能作任何的读写访问;当向文件中写入数据后,通过mmap返回的虚拟地址可以访问这部分文件内容;

mmap与内存换入换出

  • 由前面的介绍我们知道mmap不管是映射磁盘文件,还是作匿名映射,最终都会分配物理内存页,因此这个物理内存页在内存紧张时就有备换出的可能,当然mmap提供了MAP_LOCKED,可以锁定内存不被换出,我们不考虑这种情况;
  • 如果使用mmap映射的是磁盘文件,其存在物理页的内容会被清空,pte将记录这种情况,再次需要访问时,会重新读取磁盘文件,缓存在page cache中;
  • 如果使用mmap作匿名映射,没有相关联的磁盘文件(或者使用MAP_PRIVATE方式映射磁盘文件),发生内存换出时,将被交换到swap中,swap实际上也对应着磁盘块,最终也是写在磁盘上;

关于360技术:360技术是360技术团队打造的技术分享公众号,每天推送技术干货内容,更多技术信息欢迎关注“360技术”微信公众号

mmap映射大于4g的文件_浅谈mmap_刘伟相关推荐

  1. mmap映射大于4g的文件_尴尬,win10镜像文件install.wim大于4G,如何将它装进U盘

    大多数现代操作系统都将UEFI作为默认固件,这是一件好事,但是,要想在UEFI系统上安装Windows 10,需要使用FAT32文件系统创建可引导的驱动器,而FAT32文件系统只能存储小于4GB的文件 ...

  2. mmap映射大于4g的文件_iOS文件内存映射——MMAP

    前言 最近一段项目上总是出现一些因为文件没有及时保存而产生的问题,因此小编就在网上寻找到了这个文件存储方法mmap,这里为大家进行下简单的介绍. 简介 首先我们需要对iOS中各App的运行环境进行了解 ...

  3. 伺服驱动器生产文件_浅谈伺服驱动器的工作原理

    原标题:浅谈伺服驱动器的工作原理 目前,主流的伺服驱动器均采用数字信号处理器(DSP)作为控制核心,可以实现比较复杂的控制算法,实现数字化.网络化和智能化.功率器件普遍采用以智能功率模块(IPM)为核 ...

  4. docker -v 覆盖了容器中的文件_浅谈docker中宿主机和容器之间互相copy文件的两种方式,欢迎补充...

    在dokcer的日常使用过程中,我们可能会遇到将宿主机内文件/目录copy到容器内,或者将容器的文件/目录copy到宿主机中,下面我们就来简单的谈一下关于这种情况的两种操作. 1.Docker cp命 ...

  5. docker -v 挂载文件_浅谈关于docker中数据卷的操作,附带案例

    Volume数据卷的由来: Docker镜像是由多个文件系统(只读层)叠加而成.当我们启动一个容器的时候,Docker会加载只读镜像层并在其上添加一个读写层.如果运行中的容器修改了现有的一个已经存在的 ...

  6. java转换成class文件_浅谈JVM编译原理-.java文件转变为.class文件的过程

    为什么需要编译? 我们平常写代码,有规范的命名方式,都能够看得懂,但是我们写的代码计算机是看不懂的,所以需要编译,也就是一个转换的过程,如下: 1.这个是咱们平时写的代码,就比较好理解,对人友好 2. ...

  7. 大于4g的文件如何拷贝到u盘?

    如果你想要将大于4G的文件拷贝到U盘,可能会收到提示文件过大,无法复制到U盘,这该怎么办?主要是因为有些U盘是FAT32格式的,所以只需要将FAT32格式转化成NTFS格式即可. 系统之家一键重装系统 ...

  8. 如何让U盘支持大于4G的文件

    U盘通常是FAT(*)格式,不能支持大于4G的文件.为了实现这个目的,通常可以把U盘格式化成NTFS或者exFAT,这两种文件系统都支持大于4G的文件. 一.格式化成NTFS 第一步 首先我们把优盘插 ...

  9. 超过4g的文件怎么上传到linux,怎么免费上传大于4G的文件到百度云 大于4G的文件不开会员怎么上传到百度云...

    4G管家appv1.0 安卓版 类型:系统工具大小:13.1M语言:中文 评分:10.0 标签: 立即下载 百度云可以非常方便大家存储一些大文件资料,而且百度云的容量也非常高,不过如果你是普通用户的话 ...

最新文章

  1. 全“芯”关注用户需求 AMD“超轻薄笔记本”杀出重围
  2. OpenKruise 如何实现 K8s 社区首个规模化镜像预热能力
  3. Struts2中的Action
  4. java类体_计算机二级考试Java类之类声明以及类体
  5. vscode新建文件的快捷键_Mac怎么创建txt文件?如何设置新建txt的快捷键?
  6. 在Python中检测*可用* CPU数量的便携方式
  7. kali linux wps 2019 删除_良心推荐!Linux系统下常用办公软件大盘点
  8. 使用oracle sql profile固定执行计划
  9. win7系统下VS2015中CUDA8.0调试程序问题
  10. Linux学习笔记(七)Linux常用命令:挂载命令
  11. C++使用librdkafka创建消费者和生产者
  12. mysql启动黑屏_红警win10黑屏和不显示菜单栏问题 只有声音没有图像的解决
  13. 数组和链表 Array and Linked-List
  14. Spark基本工作流程和作业调度
  15. 交替性注意力_注意力不足的小朋友通常都是持续性专注力
  16. [Pytorch系列-35]:卷积神经网络 - 搭建LeNet-5网络与CFAR10分类数据集
  17. 基于区块链的数据透明化:问题与挑战 Blockchain-Based Data Transparency: Issues and Challenges
  18. 国产三维CAD华天软件STNOVATION 几何造型内核CRUX IV 解析
  19. 英语美句-每日积累-03
  20. 为什么要学网络安全?如何学习网络安全?这3个理由告诉你(自己整理的50G网安资料)

热门文章

  1. hadoop容灾能力测试
  2. dojo中的dojoConfig配置
  3. 聊聊高并发(六)实现几种自旋锁
  4. match_phrase搜不出来,怎么办?
  5. 使用Elasticsearch实现推荐系统
  6. 025 资源的隔离与配置
  7. Openstack的nova-network的vlan模式扩展
  8. LINUX系统管理----GRUB笔记
  9. 美工一流的个人网站源码系列(2),不漂亮你可以不下载!
  10. (三)、Express 路由、静态文件、