Android 采取了一种有别于 Linux 的进程管理策略(Linux 的在进程活动停止后就结束该进程),Android 把这些进程都保留在内存中,直到系统需要更多内存为止。这些保留在内存中的进程通常情况下不会影响整体系统的运行速度,并且当用户再次激活这些进程时,提升了进程的启动速度。

那 Android 什么时候结束进程?结束哪个进程呢?之前普遍的认识是 Android 是依据一个名为 LRU(Last Recently Used 最近使用过的程序)列表,将程序进行排序,并结束最早的进程。XDA 的大神又进一步对这个管理机制进行研究,有了如下发现:

1)系统会对进程的重要性进行评估,并将重要性以oom_adj这个数值表示出来(较新的 Kernel 里使用的是 oom_score_adj),赋予各个进程;(系统会根据oom_adj来判断需要结束哪些进程,一般来说,oom_adj的值越大,该进程被系统选中终止的可能就越高)

2)前台程序的oom_adj值为 0,这意味着它不会被系统终止,一旦它不可访问后,会获得一个更高的oom_adj,作者推测oom_adj的值是根据软件在 LRU 列表中的位置所决定的;

3)Android 不同于 Linux,有一套自己独特的进程管理模块,这个模块有更强的可定制性,可根据oom_adj值的范围来决定进程管理策略,比如可以设定“当内存小于 X 时,结束oom_adj大于 Y 的进程”。这给了进程管理脚本的编写以更多的选择;

4)Android 将进程分为六大类:

  • 前台进程(foreground):目前正在屏幕上显示的进程和一些系统进程。举例来说,Dialer Storage,Google Search 等系统进程就是前台进程;再举例来说,当你运行一个程序,如浏览器,当浏览器界面在前台显示时,浏览器属于前台进程(foreground),但一旦你按 Home 回到主界面,浏览器就变成了后台程序(background)。我们最不希望终止的进程就是前台进程。

  • 可见进程(visible):可见进程是一些不在前台,但用户依然可见的进程,举例来说:widget、输入法等,都属于 visible。这部分进程虽然不在前台,但与我们的使用也密切相关,我们也不希望它们被终止(你肯定不希望时钟、天气,新闻等 widget 被终止,那它们将无法同步,你也不希望输入法被终止,否则你每次输入时都需要重新启动输入法)。

  • 次要服务(secondary server):目前正在运行的一些服务(主要服务,如拨号等,是不可能被进程管理终止的,故这里只谈次要服务),举例来说:谷歌企业套件,Gmail 内部存储,联系人内部存储等。这部分服务虽然属于次要服务,但很一些系统功能依然息息相关,我们时常需要用到它们,所以也太希望他们被终止。

  • 后台进程(hidden):虽然作者用了 hidden 这个词,但实际即是后台进程(background),就是我们通常意义上理解的启动后被切换到后台的进程,如浏览器,阅读器等。当程序显示在屏幕上时,他所运行的进程即为前台进程(foreground),一旦我们按 Home 返回主界面(注意是按 Home,不是按 Back),程序就驻留在后台,成为后台进程(background)。后台进程的管理策略有多种:有较为积极的方式,一旦程序到达后台立即终止,这种方式会提高程序的运行速度,但无法加速程序的再次启动;也有较消极的方式,尽可能多的保留后台程序,虽然可能会影响到单个程序的运行速度,但在再次启动已启动的程序时,速度会有所提升。这里就需要用户根据自己的使用习惯找到一个平衡点。

  • 内容供应节点(content provider):没有程序实体,仅提供内容供别的程序去用的,比如日历供应节点,邮件供应节点等。在终止进程时,这类程序应该有较高的优先权。

  • 空进程(empty):没有任何东西在内运行的进程,有些程序在程序退出后,依然会在进程中驻留一个空进程,这个进程里没有任何数据在运行,作用往往是提高该程序下次的启动速度或者记录程序的一些历史信息。这部分进程无疑是应该最先终止的。

实践

说完理论,说些实践的东西 —— 怎样管理这六类进程?如何来设置进程管理模块是这部分说的内容。

首先说下 LMK 模块配置,Android 使用了一个 Kernel 模块与 Android Framework 协作管理内存,叫做 Low Memory Killer(LMK)。LMK 的配置参数可以从/sys/module/lowmemorykiller/parameters/minfree查看到,例如:

18432,23040,27648,32256,55296,80640

其值对应的进程为:

foreground/visible/secondary server/hidden/content provider/empty

其值的对应单位是 memory page,1 page = 4 KB,18432 page 转换至 MB 等于18432*4/1024=72,所以上面的/sys/module/lowmemorykiller/parameters/minfree以 MB 换算后为:

72/90/108/126/216/315

从软件数值的设置不难看出结束进程的顺序:

empty > content provider > hidden > secondary server > visible > foreground

表示当可用内存低于 315 MB 时,中止 empty;当可用内存低于 216 MB 时,中止 content providers……依此类推。

其次是软件,例如使用 MinFreeManager(Play 商店有下载),用于设置这六类进程的管理策略。

软件运行后有六个输入框,在输入框中只能输入数字,这些数字代表了这类进程的处理策略,同样比如 Foreground App 下的输入框显示 6,就表示当可用内存低于 6 MB 时,终止 Foreground App。下面的类似,如 Empty App 下的输入框显示 24,则表示当可用内存低于 24 MB 时,终止 Empty App。

例如以6,8,16,20,22,24配置为例,存在的一些问题是:

  • 各类进程的管理策略的阀值相当接近:6,8,16,20,22,24,最大的相差也不到 8 MB,在实际程序运行中,很容易导致多种类型的进程同时被关闭。如可用内存在 25 时,突然启动照相程序,系统可用内存急速上升,可能会导致空进程、内容供应节点、后台进程、次要服务等同时被关闭。

  • 阀值上限较低:一般手机启动后,可用内存在 50-100 左右,但随着手机的使用,可用内存会逐步减少,最后降低到 24 MB 左右,则系统开始启动进程管理机制,开始结束进程,但这个阀限制设在了 24 MB,相对来说偏低。其结果会导致系统使用一段时间后,整体速度变慢。很明显的就是,当手机长时间使用后,开启电话拨号,相册,照相机等应用时,系统的反应速度极慢。

基于以上几个问题,不难看出,我们修改的目标也将非常明确,主要解决两个矛盾:

  • 拉开各进程的阀值层次,使得进程管理机制能更有效得工作

  • 提升阀值上限,空出更多的空余内存,以提升系统整体的运行速度

进程管理策略设置原则

前台进程、可见进程和次要服务是与用户体验息息相关的内容,这部分的进程管理策略要相对保守,给这些进程留下足够的运行空间;压榨无用进程,腾出内存空间给主要程序使用。

实例

以 1 G 运行内存为例,下面总结了几种设置方式,适应不同的使用需要,实例仅供学习参考。

游戏玩家/重度浏览器使用者配置

用户特点:长时间专注于某一特定的,高内存需求的程序,对多任务的需求不高。

配置参数:

Foreground:6
Visible:8
Secondary Server:16
Hiden App:80
Content Provider:90
Empty:100

配置理念:压榨后台进程,内容供应节点和空进程,将内存尽可能多得留给前台进程和系统,提升游戏速度和浏览器体验

优点:程序启动和运行的速度最快

缺点:多任务处理不理想,开启程序较多时,后台进程会被终止

多任务配置

用户特点:同时运行多个应用程序,需要经常在多个程序间切换

配置参数:

Foreground:6
Visible:8
Secondary Server:16
Hiden App:20
Content Provider:60
Empty:100

配置理念:压榨空进程,给内容供应节点留有一定空间,最大限度提升后台程序的使用空间,提升多任务的处理能力

优点:运行多个程序时,由于可支配内存较多,后台程序不容易被终止

缺点:程序启动的速度和整体系统的运行速度可能会比游戏玩家配置略慢一些,由于经常运行多任务,平时系统的响应速度会受到一定影响

轻度用户/女生专用配置

用户特点:手机的主要功能是短信和电话,偶尔用用相机自拍

配置参数:

Foreground:6
Visible:8
Secondary Server:16
Hiden App:24
Content Provider:32
Empty:48

配置理念:压榨空进程,给内容供应节点留有一定空间,最大限度提升后台程序的使用空间,提升多任务的处理能力

优点:比较均衡的配置,提升了系统的可用内存,使得系统的整体速度得到了提高,拉开了各级进程的管理策略层次,使得管理机制更有效率

缺点:比较均衡的配置,无明显缺点


参考文章:How to Tweak Android Low Memory Killer to Your Needs