Ashmem匿名共享内存

Android的匿名共享内存(Ashmem)机制基于Linux内核的共享内存,但是Ashmem与cache shrinker关联起来,增加了内存回收算法的注册接口,因此Linux内存管理系统将不再使用内存区域加以回收。Ashmem以内核驱动的形式实现,在文件系统中创建/dev/ashmem设备文件。如果进程A与进程B需要共享内存,进程A可通过open打开该文件,用ioctl命令ASHMEM_SET_NAMEASHMEM_SET_SIZE设置共享内存的名称和大小。mmap使用handle获得共享的内存区域;进程B使用同样的handle,由mmap获得同一块内存。handle在进程间的传递可通过Binder等方式实现。

为有效回收,需要该内存区域的所有者通知Ashmem驱动。通过用户,Ashmem驱动程序,以及Linux内存管理系统的协调,使内存管理更适应嵌入式移动设备内存较少的特点。Ashmem机制辅助内存管理系统来有效管理不再使用的内存,同时通过Binder进程通信机制实现进程间的内存共享

Ashmem不但以/dev/ashmem设备文件的形式适应Linux开发者的习惯,而且在Android系统运行时和应用程序框架层提供了访问接口。其中,在系统运行时提供了C/C++调用接口,在应用程序框架层提供了Java调用接口。而实际上,应用程序框架层的Java调用接口是通过JNI方法来调用系统运行时的C/C++调用接口的,最后进入到内核空间的Ashmem驱动程序中。

LMK机制

Android的软件协议栈由操作系统内核,中间件与应用程序组成。虽然基于Linux操作系统内核,android进程的内存管理与Linux仍有区别。Android的应用程序由java语言编写,运行于Java虚拟机之上,但是,Android的java虚拟机Dalvik与传统的Java虚拟机是有区别的。Dalvik采用基于寄存器的虚拟机优化实现,确保多个虚拟机实例同时运行,借助Linux内核服务,实现安全保护,线程管理,底层进程与内存管理等功能。Dalvik虚拟机运行.dex格式的Dalvik可执行文件。.dex格式由android工具将java格式的class文件转化而来,并且进一步优化,降低内存占用。

Android的每个应用程序都有一个独立的Dalvik虚拟机实例,并且运行于独立的进程空间。Android运行时(Runtime)与虚拟机都运行于Linux操作系统之上,借助操作系统服务进行底层内存管理并访问底层设备的驱动程序。

但是,不同于Java与.NET,Android运行时同时管理进程的生命周期。为确保应用程序的响应性,可以在必要时停止甚至杀死某些进程,向更高优先级的进程释放资源。具体原则如下:

  • 应用程序的进程优先级决定哪些进程可以被杀死以释放资源,而应用程序的优先级取决于其组件的最高优先级。

  • 当两个进程具备相同的优先级时,通常处于低优先级时间最长的进程先被杀死,以释放资源。

  • 进程优先级同时取决于进程间的依赖关系:例如,第一个进程依赖于第二 个进程提供的服务(Services)或内容提供者(Content Provider),则第二个进程至少具备与第一个进程同样的优先级。

Android系统可以同时运行多个应用程序。由于启动与运行一个应用程序需要一定的时间开销,为了加快运行速度,Android并不会立即杀死一个退出的程序,而是让它驻留在内存中,以便下次运行时迅速启动但是,随着程序越来越多,内存会出现不足。当Android系统需要某一进程释放资源为其他进程所用时,系统使用所谓的“LowMemoryKiller”杀死进程以释放资源。LowMemoryKiller在Linux内核中实现,按程序的重要性来决定杀死哪一个应用。因此,必须妥善设置进程的优先级,否则该进程可能在运行过程中被系统杀死。

Android自动管理打开并运行于后台的应用程序,单个程序都有一个oom_adj值值越小,优先级越高,被杀死的可能性越低。Android将程序的重要性分成几类。

1. 前台进程(Active Process)oom_adj值为0。前台进程为正在与用户交互 的应用程序。为响应前台进程,Android可能要杀死其他进程以收回资源。前台进程分为以下几类:

  • 活动(Activity)正在前台接收用户输入事件。

  • 活动,服务与广播接收器正在执行一个onReceive事件处理函数。

  • 服务正在执行onStart,onCreate或onDestroy事件处理函数。

2. 已启动服务的进程(Started Service Process)oom_adj值为0。这类进程包含一个已启动的服务。服务并不直接与用户输入交互,因此服务的优先级低于可见活动的优先级。但是,已启动服务的进程仍然被认为是前台进程,只有在活动及可见活动需要资源时,已启动服务的进程才会被杀死。

3. 可见进程(Visible Process)oom_adj值为1。活动(Activity)是可见的,但并不在前台,或者不响应用户的输入。例如,Activity被非全屏的Activity或透明的Activity所遮挡。包含此类可见Activity的进程被称为可见进程。只有在非常少有的极端情况下,此类进程才会被杀死以释放资源。

4. 后台进程(Background Process)oom_adj值为2。这类进程不包含任何可见的活动与启动的服务。通常大量后台进程存在时,系统会采用(last-seen-firest-killl)后见先杀的方式,释放资源供前台进程使用。

5. 主界面(Home Process)oom_adj值为4

6. 隐藏进程(Hidden Process)oom_adj值为7

7. 内容提供者(Content Provider)oom_adj值为14

8. 空进程(Empty Process)oom_adj值为15。既不提供服务,也不提供内容的进程。

Android系统通常有一个内存警戒值与oom_adj值的对应表:每个内存警戒值对应一个oom_adj值。当系统内存低于警戒值时,所有大于oom_adj值的进程都可被杀死!内存警戒与oom_adj值对应关系如下表:

进程各类
oom_adj值
内存警戒值(以4KB为单位)
前台进程/服务进程
0
1536
可见进程
1
2048
后台进程
2
4094
隐藏进程
7
5120
内容提供者
14
5632
空进程
15
6144

当可用内存小于6144 * 4K = 24MB时,开始杀死所有的空进程,当可用内存小于5632 * 4K = 22MB时,开始杀死所有内容提供者与空进程。上表的设置可以通过修改以下两个文件实现:

  • /sys/module/lowmemorykiller/parameters/adj

  • /sys/module/lowmemorykiller/parameters/minfree

例如,把minfree最后一项改为32 * 1024,那么当可用内存小于128MB时,就开始杀所有的空进程。

但是,当过多进程在内存中未被释放,系统反应速度会降低,造成用户满意度降低。用户可以自行使用如task killer与task Manager之类的工具软件手动杀死不必要的后台进程与空进程,强制释放资源。

更多相关文章

  1. Android系统(245)---SystemServer进程的创建流程
  2. android 4.04的应用程序启动过程及与Zygote的交互(基于静态源码分
  3. Android应用程序的生命周期
  4. Android中native进程内存泄露的调试技巧
  5. 分析Android(安卓)根文件系统启动过程(init守护进程分析)
  6. 关于 Android(安卓)进程保活,你所需要知道的一切(转)
  7. Android内存泄漏查找
  8. Android多进程模式
  9. Android进程的内存管理分析

随机推荐

  1. mysql中插入中文时显示乱码
  2. org.hibernate.hql.internal.ast.QuerySy
  3. mysql数据库连接查询
  4. Mysql 数据分页处理(Node.js的实现)
  5. linux 下怎么安装MySql
  6. mysql-ubuntu卸载安装mysql
  7. MySQL数据目录结构
  8. 如何使用mysql 命令行 查看mysql表大小、
  9. MySQL手动安装步骤
  10. 关于mysql 中的limit 偏移量较大时 的