本文链接: 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程序在写入内存后就挂掉了,只要操作系统工作正常,数据就会写入磁盘。
如果电源故障或者主机瘫痪,有可能内存映射文件还没有写入磁盘,意味着可能会丢失一些关键数据。

参考

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

Android中使用mmap

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

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

Android mmap 文件映射到内存介绍的更多相关文章

  1. iOS将大文件映射到内存(读取大文件)

    http://blog.csdn.net/xyt243135803/article/details/40995759 在<中国区GPS偏移纠正(适用于Google地图)>一文中曾读取一个7 ...

  2. [android] 保存文件到手机内存

    /*****************2016年5月4日 更新*******************************/ 知乎:Android 没有沙盒保护机制吗,WhatsApp 信息为何可被随 ...

  3. MMAP文件内存映射

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  4. (转)mmap和shm共享内存的区别和联系

    共享内存的创建 根据理论: 1. 共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复制,所以是最快的一种进程间通信机制.共享内存可以通过mmap()映射普通文件 (特殊情况下还可以采用 ...

  5. System V共享内存介绍

    (一)简单概念 共享内存作为一种进程间通信的方式,其相较于其他进程间通信方式而言最大的优点就是数据传输速率快.其内部实现的方式采用了Linux进程地址空间中的mmap文件映射区,将文件内容直接映射到各 ...

  6. (理论篇)从基础文件IO说起虚拟内存,内存文件映射,零拷贝

    为了快速构建项目,使用高性能框架是我的职责,但若不去深究底层的细节会让我失去对技术的热爱. 探究的过程是痛苦并激动的,痛苦在于完全理解甚至要十天半月甚至没有机会去应用,激动在于技术的相同性,新的框架不 ...

  7. 《Java核心技术卷二》笔记(二)文件操作和内存映射文件

    文件操作 上一篇已经总结了流操作,其中也包括文件的读写.文件系统除了读写以为还有很多其他的操作,如复制.移动.删除.目录浏览.属性读写等.在Java7之前,一直使用File类用于文件的操作.Java7 ...

  8. 文件映射mmap

    磁盘与内存的映射就是文件映射,说这个问题之前我们先说下swap,因为   这个问题让我很容易想起swap,linux swap 是交换分区的意思,在内存不   够的情况下,操作系统先把内存与磁盘的sw ...

  9. 关于Android中图片大小、内存占用与drawable文件夹关系的研究与分析

    原文:关于Android中图片大小.内存占用与drawable文件夹关系的研究与分析 相关: Android drawable微技巧,你所不知道的drawable的那些细节 经常会有朋友问我这个问题: ...

随机推荐

  1. 一段代码分清global和nonlocal

    废话不多说,直接代码啊~~~ a=999 b=99999 def test1(): a=888 b=88888 print('a={}'.format(a)) print('b={}'.format( ...

  2. arukas 樱花免费docker容器获取IP和端口

    arukas 樱花免费docker容器,可以安装linux系统,但是每隔一段时间会重启,重启以后IP地址和映射到公网的端口都会变,获取IP和端口,我研究了很久终于找到了C#获取IP和端口的办法,用来搭 ...

  3. CSV Data Set Config 拓展开发

    1.目的 在日常的性能测试项目中,经常会遇到参数化的问题,我们所熟知的LR工具对参数化支持非常友好,然而JMeter相对逊色一些.大家都知道在使用JMeter工具参数化时常用CSV Data Set ...

  4. CF553C Love Triangles(二分图)

    Tyher推的好题. 题意就是给你一些好边一些坏边,其他边随意,让你求符合好坏坏~,或者只包含好好好的三元环的无向图个数. 坏坏的Tyher的题意是这样的. 再翻译得更加透彻一点就是:给你一些0(好边 ...

  5. [HNOI2009]双递增序列(动态规划,序列dp)

    感觉这个题还蛮难想的. 首先状态特别难想.设\(dp[i][j]\)表示前i个数,2序列的长度为j的情况下,2序列的最后一个数的最小值. 其中1序列为上一个数所在的序列,2序列为另外一个序列. 这样设 ...

  6. Python程序包的构建和发布过程

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  7. 为什么操作DOM会影响WEB应用的性能?

    面试官经常会问你:"平时工作中,你怎么优化自己应用的性能?" 你回答如下:"我平时遵循以下几条原则来优化我的项目.以提高性能,主要有:" a. 减少DOM操作的 ...

  8. GUID做主键真的合适吗

    在一个分布式环境中,我们习惯使用GUID做主键,来保证全局唯一,然后,GUID做主键真的合适吗? 其实GUID做主键本身没有问题,微软的很多项目自带DB都是使用GUID做主键的,显然,这样做是没有问题 ...

  9. Redis学习总结(二)--Redis数据结构

    Redis支持六种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). 结构类型 存储的值 string 可以是字符串.浮 ...

  10. MSIL实用指南-数据类型转换

    一.类的强制转换1.转换成某个类用Castclass指令.实例代码:ilGenerator.Emit( OpCodes.Castclass , typeof(ClassA) ); 2.转换成某个值类型 ...