当前位置: 首页 > news >正文

APP优化 —— MMAP内存映射

mmap

一种内存映射文件的方法

mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。

头文件 <sys/mman.h>

函数原型

void* mmap(void* start,[size_t](https://baike.baidu.com/item/size_t/8101179?fromModule=lemma_inlink) length,int prot,int flags,int fd,off_t offset);
​
int [munmap](https://baike.baidu.com/item/munmap/4568227?fromModule=lemma_inlink)(void* start,size_t length);

映射条件

mmap()必须以PAGE_SIZE为单位进行映射,而内存也只能以页为单位进行映射,若要映射非PAGE_SIZE整数倍的地址范围,要先进行内存对齐,强行以PAGE_SIZE的倍数大小进行映射。

mmap基础概念

mmap是一种内存映射的方法,这一功能可以用在文件的处理上,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。在编程时可以使某个磁盘文件的内容看起来像是内存中的一个数组。如果文件由记录组成,而这些记录又能够用结构体来描述的话,可以通过访问结构数组来更新文件的内容。

内存映射原理

mmap是一种内存映射文件的方法,它将一个文件映射到进程的地址空间中,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。

当磁盘地址和进程虚拟地址建立关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写数据到磁盘上,即直接完成了对文件的操作而不必在调用read/write等系统调用函数。同样的如果磁盘中内容有修改,也会直接反映到用户空间其数据改变了。

所以通过mmap映射方式可以使不同进程间共享磁盘文件,其共享对象可为普通文件或匿名文件

映射内存的分配

mmap映射区域大小必须是物理页大小(page_size)的整倍数(在Linux中内存页通常是4k)。因为内存的最小粒度是页,而进程虚拟地址空间和内存的映射也是以页为单位。为了匹配内存的操作,mmap从磁盘到虚拟地址空间的映射也必须是页。

例如,有一个文件的大小是5K,mmap函数从文件的起始位置映射5K到虚拟内存中,由于内存物理页是4K,虽然映射的文件只有5K,但是实际上映射到内存区域的内存是8K,以便满足物理页大小的整数倍。映射后对5~8K的内存区域用零填充,对这部分的操作不会报错也不会写入到原文件中。

传统I/O读写流程

  1. 用户进程发起文件数据的读请求
  2. 内核通过查找进程文件符表,定位内核已打开文件集上的文件信息,从而找到文件inode
  3. inode在address_space上查找要请求的文件页是否已缓存在页缓存中
  4. 如已在缓存页中,则直接返回这片文件页上的内容
  5. 如不在缓存页上,就会引发缺页中断。 当发生缺页中断时,内核则调用nopage函数把所缺的页从磁盘装入到内存内核中及Page Cache中。接着再发起读页面过程,从而将数据从页缓存中拷贝到用户空间中

特点:

常规文件操作为了读写效率和保护磁盘,使用了页缓存机制 页缓存处在内核空间中,不能直接被用户进程直接寻址,需要将数据从页缓存中拷贝到主内存

mmap读写流程

  • 用户进程调用进程内存映射函数库mmap,当前进程在线程虚拟地址空间中寻找一段空闲的满足要求的虚拟地址。
  1. 在当前进程的虚拟地址空间中,寻找一段满足要求的虚拟地址
  2. 为此虚拟地址分配一个虚拟内存区域,vm_area_struct结构
  3. 初始化该虚拟内存区域
  4. 插入该虚拟内存区域到进程的虚拟地址区域链表中
  • 内核同样收到请求后会调用内核的mmap函数,实现地址映射关系配对,即进程虚拟地址空间<< >>文件磁盘地址 关系映射,该映射与内核内存没有任何关联
  1. 进程调用mmap函数,内核同样会得到消息,最终内核调用自身的系统调用函数mmap。(两mmap函数不一样)
  2. 内核mmap函数通过虚拟文件系统定位到文件磁盘物理地址。
  3. 通过remap_pfn_range()建立页表,实现了文件地址和虚拟地址区域的映射关系。
  • 进程的读/写操作访问虚拟地址空间这一段地址,如果读写操作该改变了虚拟地址空间内容,则一段时间后系统会自动回写脏页面到对应的磁盘地址中,即完成了写入文件的操作。
  1. 修改的脏页面不会立即更新,而是有延时,可以通过msync()来强制同步。通过此法能将所写的内容立即保存到磁盘中

特点:

  1. 用户空间与内核空间磁盘块通过映射直接交互,不在间接通过页缓存。
  2. 文件读写操作跨过了页缓存,数据拷贝次数减少为只需一次
  3. 借助硬盘的大空间,对于大规模数据的读写避免对页内存空间大小的依赖,提高操作效率。

mmap数据读写的性能提升就在于对数据的读写拷贝次数,mmap只需要一次系统调用(一次拷贝),后续操作不需要系统调用。并且访问的数据不需要在page cache和用户缓冲区之间拷贝。

mmap读写优势

  1. 对文件的读取操作跨过了页缓存,减少了数据的拷贝次数,用内存读写取代I/O读写,提高了文件读取效率。
  2. 实现了用户空间和内核空间的高效交互方式。两空间的各自修改操作可以直接反映在映射的区域内,从而被对方空间及时捕捉。
  3. 提供进程间共享内存及相互通信的方式。不管是父子进程还是无亲缘关系的进程,都可以将自身用户空间映射到同一个文件或匿名映射到同一片区域。从而通过各自对映射区域的改动,达到进程间通信和进程间共享的目的。

如果进程A和进程B都映射了区域C,当A第一次读取C时通过缺页从磁盘复制文件页到内存中;但当B再读C的相同页面时,虽然也会产生缺页异常,但是不再需要从磁盘中复制文件过来,而可直接使用已经保存在内存中的文件数据。

可用于实现高效的大规模数据传输。内存空间不足,是制约大数据操作的一个方面,解决方案往往是借助硬盘空间协助操作,补充内存的不足。但是进一步会造成大量的文件I/O操作,极大影响效率。但凡是需要用磁盘空间代替内存的时候,mmap都可以发挥其功效。

mmap的使用

mmap的函数位于内核的<sys/mman.h> 头文件中,与其相关的几个函数也列出如下:

// 用户进程调用,    函数用于将文件映射到内存
void* mmap(void addr, size_t length, int prot, int flags, int fd, off_t offset);
​
// 函数用于取消映射,进程在映射空间对共享内容的改变并不直接写回到磁盘文件中,往往在调用munmap() 后才执行该操作。
int munmap(void *addr, size_t length);
// 函数用于实现磁盘文件内容与共享内存区中的内容一致,即同步操作。
// 除了调用munmap取消映射,我们也可以调用msync()实现磁盘上文件内容与内核内存的内容一致
int msync(void * addr, size_t len, int flags);
​

mmap的使用场景

1.Linux进程的创建

Linux执行一个程序,这个程序在磁盘上,为了执行这个程序,需要把程序加载到内存中,这时也是采用的是mmap。你可以从/proc/pid/maps看到每个进程的mmap状态。

  1. 内存分配

我们使用c库的malloc申请内存,malloc的分配内存有两个系统调用,一个brk,另一个就是mmap。

mmap不仅可以映射文件,也可以映射内存,当mmap使用的flag是MAP_ANONYMOUS,称为建立匿名映射,此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。匿名映射存储的数据就是在物理内存上,不属于任何文件。malloc分配内存底层就是用mmap的匿名映射来操作的。

  1. Binder进程间通信

了解进程间通信的人都知道Android使用的是Binder进行进程间通信,它的效率高于Linux其他传统的进程间通信,因为它只要一次拷贝,而之所以只需要进行一次拷贝的原因就在于使用了mmap。

最后,以上就是app深度优化需要学习的MMAP内存映射的原理解析以及使用方法;跟多Android核心技术或是Android性能优化的学习;可以点击《Android核心优化性能学习手册》。点击查看类目

mmap优缺点

优点

  • mmap 防止数据丢失,提高读写效率
  • 精简数据,以最少量的数据局量表示最多的信息,减少数据大小
  • 增量新增,避免每次数据新增时的全量写入
  • mmap对文件的读写操作只需要对磁盘到用户主存的一次数据拷贝过程,减少了数据的拷贝次数,提高文件读写效率。
  • mmap使用逻辑内存对磁盘文件进行映射,操作内存就相当于操作文件,不需要开启线程,操作mmap的速度和操作内存的速度一样快。
  • mmap提供一块随时写入的内存,app只管往里写入数据,由操作系统如内存不足。进程退出时负责将内存写回到文件。不必担心crash导致数据丢失。
  • mmap的适用场景是大文件的频繁读写,这样就可以节省很多IO的耗时。
  • 即使进程意外死亡, 也能够通过 Linux 内核的保护机制, 将进行了文件映射的内存数据刷入到文件中, 提升了数据写入的可靠性

缺点:

  • 因为mmap是按照页存储方式进行存储,每页4096字节,如果数据只有100字节,则正页将有大大的浪费。
  • 写回文件的工作由系统负责,但是并不是实时的,是定期写回到磁盘的,中间如果发生内核崩溃、断电等,还是会丢失数据,不过可以通过msync将数据同步回磁盘。

相关文章:

APP优化 —— MMAP内存映射

mmap 一种内存映射文件的方法 mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上&#xff0c;如果文件的大小不是所有页的大小之和&#xff0c;最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。 头文件 <sys/mman.h> 函数原型 v…...

paddle.vision 与 torchvision 中的box NMS使用方式

torchvision 中有多个用于计算 BBox NMS 的 API, 在本篇氵文中, 使用 torchvision.ops.boxes.batched_nmspaddle.vision 中通过 paddle.vision.ops.nms 来进行多个 Box 的 NMS 操作 1. torchvision 中 batched_nms 操作 torchvision batched_nms def batched_nms(boxes: to…...

php mysql校园帮忙领取快递平台

1、后台管理员用户名hsg 密码hsg 2、开发语言&#xff1a;PHP&#xff0c;数据库为MySql 3、数据库连接字符串在conn.php中修改 4、运行环境wamp5.1.7或者appserv2.5.9 5.程序编码gbk.不支持php5.3以上版本 6.本人发布的程序一律享有免费运行一次…...

C/C++开发,无可避免的内存管理(篇二)-约束好跳脱的内存

一、养成内存管理好习惯 1.1 养成动态对象创建、调用及释放好习惯 开发者手动接管内存分配时&#xff0c;必须处理这两个任务。分配原始内存时&#xff0c;必须在该内存中构造对象&#xff1b;在释放该内存之前&#xff0c;必须保证适当地撤销这些对象。如果你的项目是c项目&am…...

【Java】让我们对多态有深入的了解(九)

目录 &#xff08;1&#xff09;接口的基本介绍​编辑 &#xff08;2&#xff09;接口的注意事项和细节 1.接口不能被实例化 2.接口中所有方法是public方法&#xff0c;接口中的抽象方法&#xff0c;可以不用abstract修饰 3.一个普通类实现接口&#xff0c;必须将接口所有…...

12 个适合做外包项目的开源后台管理系统

1.D2admin 开源地址&#xff1a;https://github.com/d2-projects/d2-admin 文档地址&#xff1a;https://d2.pub/zh/doc/d2-admin/ 效果预览&#xff1a;https://d2.pub/d2-admin/preview/#/index 开源协议&#xff1a;MIT 2.vue-element-admin 开源地址&#xff1a;https…...

鼠标更换指针图案和更改typora的主题

鼠标更换指针图案 由此偶然看见好几个朋友都使用了新的图案替换掉了原有的鼠标图案&#xff0c;今天寻思自己也换一个图案 主要是觉得鼠标大一点儿会好看一些&#xff0c;所以就找了一些教程 官方教程&#xff0c;小的变动 当然最多的是官方教程&#xff0c;如果你只是想要…...

【洛谷 P1563】[NOIP2016 提高组] 玩具谜题(模拟+结构体数组+指针)

[NOIP2016 提高组] 玩具谜题 题目背景 NOIP2016 提高组 D1T1 题目描述 小南有一套可爱的玩具小人, 它们各有不同的职业。 有一天, 这些玩具小人把小南的眼镜藏了起来。 小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外。如下图: 这时 singer 告诉小南一个谜…...

阿里测试经验7年,从功能测试到自动化测试,我整理的超全学习指南

做测试七年多&#xff0c;有不少人问过我下面问题&#xff1a; 现在的手工测试真的不行了吗&#xff1f; 测试工程师&#xff0c;三年多快四年的经验&#xff0c;入门自动化测试需要多久&#xff1f; 自学自动化测试到底需要学哪些东西&#xff1f; 不得不说&#xff0c;随着…...

Educational Codeforces Round 143 (Rated for Div. 2)

Educational Codeforces Round 143 (Rated for Div. 2) D. Triangle Coloring 思路&#xff1a; 每个环都需要取最大值&#xff0c;那么我们讨论一个环获得最大值选的两条边的可能取法&#xff1a; 显然&#xff1a;如果三边相等&#xff0c;这个环有3种取法。如…...

业务代码编写过程中如何「优雅的」配置隔离

思考 不同的处理方式 1.常规的处理方式&#xff0c;通过某种规则判断区分代码环境 // 获取环境标识 const env getCurrentEnv();if (env dev) {// do something } else if (env test) {// do something } else if (env prod) {// do something } 分析&#xff1a; 1.此种…...

English Learning - L2-2 英音地道语音语调 2023.02.23 周四

English Learning - L2-2 英音地道语音语调 2023.02.23 周四查音标的工具怎么练习效果好准备工作大小声练习大元音开口度的对比舌位对比复习后元音 /ɑː/ /ɔː/ /uː//ɑː//ɔː//uː/前元音 /iː/发音技巧对应单词的发音对应句子的发音常见的字母组合中元音 /ɜː/发音技巧…...

java:线程等待与唤醒 - Object的wait()和notify()

java&#xff1a;线程等待与唤醒 - Object的wait()和notify() 1 前言 java使用Object类的wait()和notify()方法&#xff0c;可以实现线程等待和唤醒&#xff08;Object类为所有类的父类&#xff0c;即所有类天然具有线程等待和唤醒的方法&#xff0c;一般使用Object类的wait(…...

实现弹窗功能并修改其中一个系数

把鼠标放在number-info上面,会是一个delon/chart的类库,可以在NG-ALAIN上找到阅读NG ALAIN的图表,以及number-info样式,数据文本 它拥有[title] [subtitle]两个可以是TemplateRef类型的,而template可以在里面放一些东西,比如按钮,所以可以放一个修改按钮 这里刚开始把template放…...

vue-draggable浏览器拖拽event事件对象拖动时 DragEvent path undefined

场景&#xff1a; 在做组件拖拽过程中&#xff0c;需要获取到触发元素冒泡过程中的所有元素&#xff0c;所以使用了event.path属性。在Chrome下正常运行&#xff0c;但是在FireFox下测试时发现&#xff0c;完犊子&#xff0c;失效了&#xff0c;通过问题排查&#xff0c;发现了…...

【云原生】搭建k8s高可用集群—20230225

文章目录多master&#xff08;高可用&#xff09;介绍高可用集群使用技术介绍搭建高可用k8s集群步骤1. 准备环境-系统初始化2. 在所有master节点上部署keepalived3.1 安装相关包3.2 配置master节点3.3 部署haproxy错误解决3. 所有节点安装Docker/kubeadm/kubelet4. 部署Kuberne…...

LeetCode121_121. 买卖股票的最佳时机

LeetCode121_121. 买卖股票的最佳时机 一、描述 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最…...

收割不易,五面Alibaba终拿Java岗offer

前言 前段时间有幸被阿里的一位同学内推&#xff0c;参加了阿里巴巴Java岗位的面试&#xff0c;本人19年双非本科软件工程专业&#xff0c;目前有一年半的工作经验&#xff0c;面试前就职于一家外包公司。如果在自己本人拿到offer之前&#xff0c;如果有人告诉我一年工作经验可…...

【离线数仓-4-数据仓库设计-分层规划构建流程】

离线数仓-4-数据仓库设计-分层规划&构建流程离线数仓-4-数据仓库设计-分层规划&构建流程1.数据仓库分层规划2.数据仓库构建流程1.数据调研1.业务调研2.需求分析3.总结2.明确数据域3.构建业务总线矩阵&维度模型设计4.明确统计指标1.指标体系相关概念1.原子指标2.派生…...

SQL零基础入门学习(十一)

SQL零基础入门学习&#xff08;十&#xff09; SQL NOT NULL 约束 NOT NULL 约束强制列不接受 NULL 值。 NOT NULL 约束强制字段始终包含值。这意味着&#xff0c;如果不向字段添加值&#xff0c;就无法插入新记录或者更新记录。 下面的 SQL 强制 “ID” 列、 “LastName” …...

排序基础之插入排序

目录 前言 一、什么是插入排序 二、实现插入排序 三、插入排序优化 四、插入排序的特性 前言 上一篇中我们说到了《排序基础之选择排序》&#xff0c;这一篇我们来学习一下排序算法中的另一种基础排序算法——插入排序。 一、什么是插入排序 简单来说就是&#xff1a;每…...

LabVIEW控制DO通道输出一个精确定时的数字波形

LabVIEW控制DO通道输出一个精确定时的数字波形如何使用数据采集板卡的DO通道输出一个精确定时的数字波形&#xff1f;解答:产生一个数字波形首先需要创建一个布尔数组&#xff0c;把波形序列信息放到该布尔数组中&#xff0c;然后通过一个布尔数组至数字转换vi来产生数字波形。…...

openpnp - 零碎记录

文章目录openpnp - 零碎记录概述笔记配置文件保存无效必须在查找问题之后, 才能保存配置文件如果想找出配置动作引起的配置内容变化, 还是要尝试保存后, 比对变化才行ENDopenpnp - 零碎记录 概述 这段时间, 正在配置校准手头的openpnp设备, 用的官网最新的openpnp2.0. 由于o…...

Qt编写微信支付宝支付

文章目录一 微信支付配置参数二 支付宝支付配置参数三 功能四 Demo效果图五 体验地址一 微信支付配置参数 微信支付API&#xff0c;需要三个基本必填参数。 微信公众号或者小程序等的appid&#xff1b;微信支付商户号mchId&#xff1b;微信支付商户密钥mchKey&#xff1b; 具…...

LeetCode 剑指 Offer 64. 求1+2+…+n

求 12…n &#xff0c;要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句&#xff08;A?B:C&#xff09;。 示例 1&#xff1a; 输入: n 3 输出: 6 限制&#xff1a; 1 < n < 10000 解法一&#xff1a;利用逻辑运算符的短路&#xf…...

Mapper代理开发

MyBatis快速开发https://blog.csdn.net/weixin_51882166/article/details/129204439?spm1001.2014.3001.5501 使用Mapper代理方式完成 定义与SQL映射文件同名的Mapper接口 &#xff0c;将Mapper接口和SQL映射文件放置同一目录结构 新建接口和包&#xff1a; 将Mapper接口和…...

为什么在连接mysql时,设置 SetConnMaxIdleTime 没有作用

目录测试1go 1.15.15go 1.17.12测试2go 1.15.15go 1.17.12参考在使用golang 连接 mysql时&#xff0c;为了节省连接资源&#xff0c;在连接使用过后&#xff0c;希望在指定长度时间不再使用后&#xff0c;自动关闭连接。 这时&#xff0c;经常会使用SetConnMaxLifetime()&#…...

嵌入式开发利器

前言 俗话说&#xff0c;工欲善其事必先利其器&#xff0c;做嵌入式开发首先需要选择好的工具&#xff0c;对的工具&#xff0c;工具选对了能事半功倍&#xff0c;节省很多时间&#xff0c;那些开发大佬一般都会使用各种各样的工具&#xff0c;不同的环节使用不同的工具&#…...

Qt 的QString类的使用

Qt的QString类提供了很方便的对字符串操作的接口。 使某个字符填满字符串&#xff0c;也就是说字符串里的所有字符都有等长度的ch来代替。 QString::fill ( QChar ch, int size -1 ) 例&#xff1a; QString str "Berlin";str.fill(z);// str "zzzzzz"…...

django项目部署(腾讯云服务器centos)

基本步骤&#xff1a; 购买腾讯云服务器并配配置好 >> 本地项目依赖收集准备 >> 上传项目等文件到服务器 >> 服务器安装部署软件和python环境 >> 开始部署&#xff08;全局来看就这5个步骤&#xff09; 目录 目录 1. 购买腾讯云服务器并配配置好 …...