本文链接: Android mmap 文件映射到内存介绍

Android开发中,我们可能需要记录一些文件。例如记录log文件。如果使用流来写文件,频繁操作文件io可能会引起性能问题。
为了降低写文件的频率,我们可能会采用缓存一定数量的log,再一次性把它们写到文件中。如果app异常退出,我们有可能会丢失内存中的log信息。
那么有什么比较稳妥的写文件方式,既能降低io,又能尽可能地保证数据被写入文件呢?

mmap简介

mmap概念

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

特点:实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。如下图所示:

mmap内存映射原理

mmap内存映射的实现过程,总的来说可以分为三个阶段:

应用进程启动映射,在进程的虚拟地址空间中,寻找一段空闲的满足要求的连续的虚拟地址作为映射区域;
调用系统函数mmap,实现文件物理地址和进程虚拟地址的一一映射;
应用进程对映射区域访问,引发缺页异常,实现文件内容到物理内存(主存)的拷贝。

mmap优缺点

只有一次数据拷贝:当发生缺页异常时,直接将数据从磁盘拷贝到进程的用户空间,跳过了页缓存。
实现了用户空间和内核空间的高效交互方式:两空间的各自修改操作可以直接反映在映射的区域内,从而被对方空间及时捕捉。
提供进程间共享内存及相互通信的方式。

不管是父子进程还是无亲缘关系的进程,都可以将自身用户空间映射到同一个文件或匿名映射到同一片区域。从而通过各自对映射区域的改动,达到进程间通信和进程间共享的目的。

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

mmap注意点

对于大文件而言,内存映射比普通IO流要快,小文件则未必;
不要经常调用MappedByteBuffer.force()方法,这个方法强制操作系统将内存中的内容写入硬盘,所以如果你在每次写内存映射文件后都调用force()方法,你就不能真正从内存映射文件中获益,而是跟disk IO差不多。
读写内存映射文件是操作系统来负责的,因此,即使你的Java程序在写入内存后就挂掉了,只要操作系统工作正常,数据就会写入磁盘。
如果电源故障或者主机瘫痪,有可能内存映射文件还没有写入磁盘,意味着可能会丢失一些关键数据。

参考

  • https://stackoverflow.com/questions/258091/when-should-i-use-mmap-for-file-access
  • https://www.jianshu.com/p/187eada7b900
  • https://juejin.im/post/5c3ec9ebf265da61223a93de#heading-0
  • https://stackoverflow.com/questions/30180268/android-ndk-mmap-call-broken-on-32-bit-devices-after-upgrading-to-lollipop
  • https://stackoverflow.com/questions/33897711/android-mmap-fails-with-out-of-memory

Android中的Binder也利用的mmap。Binder传递数据时,只需要复制一次,就能把数据传递到另一个进程中。参考Binder机制介绍

Android中使用mmap

Android中使用mmap,可以通过RandomAccessFile与MappedByteBuffer来配合。参考drone开发记录 - log记录工具

通过randomAccessFile.getChannel().map获取到MappedByteBuffer。然后调用ByteBuffer的put方法添加数据。

转载于:https://www.cnblogs.com/rustfisher/p/11551372.html

Android mmap 文件映射到内存介绍相关推荐

  1. Python将文件映射到内存使用mmap.mmap()函数

    1.如何将文件映射到内存 实际案例: (1)在访问某些二进制文件时,希望能把文件映射到内存中,可以实现随机访问.(framebuffer设备文件) (2)某些嵌入式设备,寄存器被编址到内存地址空间,我 ...

  2. 22. 将文件映射到内存

    要求: 在访问某些二进制文件时,希望能把文件映射到内存中,可以像数组一样实现随机访问(例如linux的framebuffer设备文件). 某些嵌入式设备,寄存器被编址到内存地址空间,可以映射linux ...

  3. Android布局文件之 include 详细介绍

    Android布局文件之 include 详细介绍 include简介 众所周知,include就是在一个布局中,导入另一个布局文件. 优势是:相同的页面只需写一次,提高了共通布局的复用性. 下面我们 ...

  4. android保存文件到手机内存

    2019独角兽企业重金招聘Python工程师标准>>> 首先要指定文件保存的位置,在Java中,我们可以直接使用 Filefile=new File("info.txt&q ...

  5. android存到手机内存,android保存文件到手机内存

    首先要指定文件保存的位置,在Java中,我们可以直接使用 Filefile=new File("info.txt"),但是在Android中,使用这个路径文件会被保存到data/a ...

  6. mmap文件映射与缺页异常 | 图

    缺页异常

  7. linux mmap内存文件映射

    一.传统文件访问 unix访问文件的传统方法使用open打开他们,如果有多个进程访问一个文件,则每一个进程在再记得地址空间都包含有该文件的副本,这不必要地浪费了存储空间.下面说明了两个进程同时读一个文 ...

  8. 使用mmap实现文件映射

    1 文件映射 传统文件访问方式是, 首先用open系统调用打开文件, 然后使用read, write以及lseek等调用进行顺序或者随即的I/O. 这种方式是非常低效的, 每一次I/O操作都需要一次系 ...

  9. linux 文件IO与内存映射:内存映射

    前言 前面几篇我们学习了用户空间的IO缓冲区,以及IO缓冲区的分散聚合IO技术. 为了减少系统调用的次数,提升系统性能,操作系统开发者门提出了这么多的缓存技术. 但是到这里这些技术同样有不足的地方:不 ...

最新文章

  1. linux 链接ln的使用 创建和删除符号连接(软、硬链接)
  2. 分隔单词和标点符号示例
  3. Android游戏开发笔记(一)
  4. 何恺明团队最新力作SimSiam:消除表征学习“崩溃解”,探寻对比表达学习成功之根源
  5. 网络安全01-网络安全入坑
  6. python对时间日期做格式化
  7. 5.7和5.6的mysql_mysql5.6与5.7版本的区别
  8. OpenStack云计算快速入门之三:OpenStack镜像管理
  9. openmv探索_4_AprilTag标记追踪
  10. 修改fstab导致UBUNTU无法启动的解决办法
  11. 使用计算机键盘的基本步骤,键盘指法练习方法
  12. 网上打开与关闭gps几种方案测试,其中方案3可行
  13. 博客搬家工具(服务)详解
  14. 计算机中有哪些令人拍案叫绝的设计?
  15. Tomcat9及以下升级Tomcat10 部署操作
  16. HCIP 云计算资料下载 肖哥视频下载
  17. 2018年年度总结-工作成长
  18. DNS加速之“智能DNS”跟“双线加速”、“CDN加速”的区别
  19. SQLExceptioncom.mysql.jdbc.SQLError in createSQLException Incorrect string value: '\xF0\x9F\x99\x8F'
  20. 核密度聚类(一)核函数、核密度估计、核密度聚类

热门文章

  1. python3打包成exe运行 无法定位程度输入点_Pyinstaller递归错误解决方案
  2. 《大话设计模式》——外观模式
  3. ES6 中的 Set、Map 和 WeakMap
  4. [Scrum] 12.22
  5. VC++ 2005 使用BOOST库和WinPcap库
  6. 交换机设备登录账号权限1_计算机网络管理员考试试题和答案
  7. 探秘:TriCore处理器中断机制
  8. (53)FPGA基础编码D触发器(二)
  9. (131)FPGA面试题-用波形图表示D触发器的功能
  10. (02)VHDL模块介绍