Android系统的内存管理研究

  1 Android系统概述数组

  Android是Google(谷歌)公司开发的一款专门为移动设备打造的操做系统。2005年谷歌公司收购Android Inc公司后,于2007年研发了基于Linux的操做系统Android。2008年,TMobile与HTC公司共同研发了第一款Android手机——HTC G1。Android的发展速度很是惊人,仅仅3年便超过了Symbian系统,而且有强大的OEM支持以及众多的开发者。app

  Android基于Linux平台,主要由操做系统、中间件、用户界面和应用软件组成。采用的是软件堆栈的结构,操做系统的底层仅提供最基本的系统功能。在Android系统中,基本上使用的是标准的Linux2.6内核,可是Google为了让Android更适合移动手持设备,对Linux内核进行了各类优化和加强。除了Linux的通用代码外,主要包含体系结构和处理器、Android特定的驱动程序和标准的设备驱动程序3个方面的内容。Android对Linux内核的加强主要包括Alarm(硬件闹钟)、Ashmem(匿名内存共享)、Low Memory Killer(低内存管理)、Logger(日志管理)等。本文将集中分析Android的内存管理,由于Android系统是在Linux系统的基础上发展起来的,因此在介绍Linux基本的内存管理的基础上对Android的内存管理进行研究。函数

  2 Linux内存管理优化

  在内存管理方面,Linux系统新旧两个版本(2.6以前和以后)之间有很大的不一样。因为Android系统是基于Linux2.6.x内核的,本文主要介绍Linux2.6在内存管理方面的基本内容。atom

  2.1 反向映射机制url

  Linux2.6引入了基于对象的反向映射机制,这种方法为物理页面设置一个用于反向映射的链表,可是链表上的节点并非引用了该物理页面的全部页表项,而是相应的虚拟内存区域(vm_area_struct结构)。虚拟内存区域经过内存描述符(mm_struct结构)找到页全局目录,从而找到相应的页表项。相对于前一种方法来讲,用于表示虚拟内存区域的描述符比用于表示页面的描述符要少得多,因此遍历后边这种反向映射链表所消耗的时间也会少不少。spa

  page结构中与基于对象的反向映射相关的关键字段有两个:_mapcount和mapping。基于对象的反向映射的实现以下:操作系统

  struct page{.net

  atomic_t_mapcount;线程

  union{

  ……

  struct{

  ……

  struct address_space*mapping;

  };

  };

  字段_mapcount代表共享该物理页面的页表项的数目,该计数器可用于快速检查该页面除全部者以外有多少使用者在使用,初始值是-1,每增长一个使用者,该计数器加1。

  字段mapping用于区分匿名页面和基于文件映射的页面。若是该字段的最低位置被置位,那么该字段包含的是指向anon_vma结构(用于匿名页面)的指针;不然,该字段包含指向address_space结构的指针(用于基于文件映射的页面)。

  2.2 Linux页面回收

  Linux中页面回收主要经过两种方式触发:一种是由“内存严重不足”事件触发;另外一种是由后台进程kswapd触发,该进程周期性地运行,一旦检测到内存不足,就会触发页面回收操做。这里主要介绍shrink_zone()函数,此函数是Linux操做系统实现页面回收的最核心的函数之一,它实现了对一个内存区域的页面进行回收的功能。该函数主要作了两件事:

  ① 将某些页面从active链表移到inactive链表,这是由函数shrink_active_list()实现的;

  ② 从inactive链表中选定必定数目的页面,将其放到一个临时链表中,这由函数shrink_inactive_list()完成。

  该函数最终会调用shrink_page_list()去回收这些页面。

  2.3 OOMKiller机制

  OOM(Out of Memory)是标准Linux内核(kernel)的一种内存管理机制,当系统内存耗尽时,OOM会选择性的杀掉一些进程以求释放一些内存。

  Linux在2.6.36内核中修正了OOMKiller的行为,跟以前的OOMKiller相比,主要体如今3个方面:第一,将物理内存页面的使用做为基准而不是虚拟地址空间的大小;第二,导出用户策略的控制权;第三,内核有了一个简单而合理的默认策略。

  Linux下有3种Overcommit的策略:0,启发式策略;1,永远容许Overcommit,这种策略适合那些不能承受内存分配失败的应用;2,永远禁止Overcommit,这种策略下系统所能分配的内存不会超过swap+RAM*系数。在Linux系统中,只要存在Overcommit,就可能会有OOMKiller跳出来。当OOMKiller跳出来的时候,指望它能够杀掉没用的且耗内存多的程序,这就须要一个选择目标的策略。Linux下这个选择目标的策略也在随着内核的改进不断的演化。在Linux下每一个进程都会有个OOM权重,在/proc/ /oom_adj中,取值是-17~+15,取值越高,越容易被杀掉。用户能够经过设置这些值来影响OOMKiller做出决策。这个值是系统综合进程的内存消耗量、CPU时间、存活时间和oom_adj计算出的,消耗内存越多分值就会越高。除此以外,Linux在计算进程的内存消耗的时候,会将子进程所耗内存的一半同时算到父进程中。

  3 Android的低内存管理

  Android是一个多任务系统,当启澳门娱乐城动一个程序时会消耗必定的时间。为了加快运行速度,当退出一个程序时,Android并不会当即杀掉它,这样当用户从新运行该程序时,能够很快地启动。但随着系统中保留的程序愈来愈多,内存确定会出现不足,此时就有了Android的低内存管理(Low Memory Killer)机制。

  3.1 Low Memory Killer机制

  Low Memory Killer是在标准Linux kernel的OOM基础上修改而来的一种内存管理机制,基于oom_adj和占用内存的大小来选择Bad进程。对应于每一个oom_adj都有一个空闲内存的阈值,Android kernel每隔一段时间会检查当前空闲内存是否低于某个阈值。若是是,则杀死oom_adj最大的Bad进程。若有两个以上的Bad进程oom_adj相同,则杀死其中占用内存最多的进程。

  3.2 Low Memory Killer的实现

  Low Memory Killer是之内核驱动的形式实现的,该实现位于drivers/misc/lowmemorykiller.c中,经过注册Cache Shrinker实现。Cache Shrinker是标准Linux kernel回收页面的一种机制,它由内核线程kswapd监控,当空闲内存页面不足时,kswapd会调用注册的Shrinker回调函数,来回收内存页面。lowmem_shrink是这个驱动的核心实现,当内存不足时就会调用lowmem_shrink方法来杀掉某些内存。lowmem_shrink用两个数组做为选择Bad进程的依据,定义以下:

  static int lowmem_adj[6]={0,1,6,12};

  static int lowmem_adj_size=4;

  static size_t lowmem_minfree[6]={3*512,2*1024,4*1024,16*1024};

  lowmem_minfree保存空闲内存的阈值,单位是一个页面4 KB,lowmem_adj保存每一个阈值对应的优先级。lowmem_shrink首先计算当前空闲内存的大小,若是小于某个阈值,则以该阈值对应的优先级为基准,遍历各个进程,计算每一个进程占用内存的大小,找出优先级大于基准优先级的进程,在这些进程中选择优先级最大的杀死。若是优先级相同,则选择占用内存最多的进程。lowmem_shrink杀死进程的方法是向进程发送一个不能够忽略或阻塞的SIGKILL信号:force_sig(SIGKILL,selected)。

  3.3 内存管理

  Android中的内存管理分为两个部分:第一部分是当应用程序关闭后,后台对应的进程并无真正退出,以便下次再启动时可以快速启动;第二部分是当系统内存不够时,Ams会主动根据内存管理机制退出优先级较低的进程。这里主要介绍第二部分。

  Ams(Activity manager service)运行在Java环境中,而Android采用Dalvik虚拟机,应用程序和Ams运行在两个独立的虚拟机中,Ams并不会知道应用程序的内存分配状况。那内存是怎么管理的呢?在Android中运行一个Low Memory Killer进程,该进程启动时会首先在Linux内核中把本身注册为一个OOM Killer,即当Linux内核的内存管理模块检测到系统内存低的时候就会通知已经注册的OOM进程,而后这些OOM Killer就能够根据各类规则进行内存释放。当内存知足低的条件时,Linux内核管理模块通知OOM Killer,Killer则根据Ams所告知的优先级,强制退出优先级低的应用程序。

  4 Android内存优化研究

  Android内存管理机制主要是针对进程的优先级和内存占用状况来对进程进行管理的,因此对内存管理的优化也主要体如今对进程阈值的设定上。

  4.1 Android进程

  Android根据进程的重要性,将进程分为如下几类:

  ① FOREGROUD_APP(前台进程),用户正在使用的进程和一些系统进程。

  ② VISIBLE_APP(可见的进程)跟FOREGROUD_APP相似,用户正在使用或看获得,它们的区别就是VISIBLE_APP可能不是用户关注的程序,可是用户看获得,或者没有覆盖到整个屏幕,只有屏幕的一部分。

  ③ SECONDARY_SERVER(后台进程)是被切换到后台的进程,后台进程的管理策略有不少种,Android采用一种消极的方式,即尽量地保留后台程序,这样能够很好地提升再次启动的速度。

  ④ HIDDEN_APP(隐藏的程序)是用户看不见可是还在运行的程序,跟②有必定的区别。

  ⑤ CONTENT_PROVIDER(内容供应节点)没有程序实体,仅提供内容供别的进程使用,好比日历供应节点、邮件供应节点等。

  ⑥ EMPTY_APP(空进程)既不提供服务,也不提供内容。当进程退出时,系统会自动为其保留一个空进程,目的也是为了保证程序再次启动的速度。

  以上每一个进程都会有个oom_adj值,①~⑥分别为0、一、二、七、1四、15。

  除了程序的重要性,Android系统还会维护另一张表,进程优先级及阈值对应关系如表1所列。

推荐阅读:http://blog.igrow.cn/1821214/viewspace-679389

相关文章
相关标签/搜索