Android安全模型之Android安全机制(内存管理)

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之类的工具软件手动杀死不必要的后台进程与空进程,强制释放资源。

你可能感兴趣的:(android)