进程优先级
系统为了新建进程或运行更重要的进程,Android系统需要清除旧进程来回收内存。为了确定保留或终止哪些进程,系统会根据进程中正在运行的组件以及这些组件的状态,将每个进程放入“重要性层次结构”中。
进程依据其重要性可划分成5级:
- 前台进程(Foreground process)
- 可见进程(Visible process):没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。
- 服务进程(Service process):尽管服务进程与用户所见内容没有直接关联,但是它们通常在执行一些用户关心的操作(例如,在后台播放音乐或从网络下载数据)。
- 后台进程(Background process):后台进程对用户体验没有直接影响,系统可能随时终止它们,以回收内存供前台进程、可见进程或服务进程使用。
- 空进程(Empty process):保留这种进程的的唯一目的是用作缓存,以缩短下次在其中运行组件所需的启动时间。
每种状态都对应不同的进程优先级,可以通过/proc/process_pid/oom_score_adj查看优先级的值(简称为adj)。
进程状态 | adj值 | 描述 |
---|---|---|
FOREGROUND_APP_ADJ | 0 | 前台进程 |
VISIBLE_APP_ADJ | 100 | 可见进程,如有部分activity可见 |
PERCEPTIBLE_APP_ADJ | 200 | 可察觉,但不立即可见,如后台音乐播放器 |
BACKUP_APP_ADJ | 300 | 备份的进程,杀掉没有致命错误但最好不杀 |
HEAVY_WEIGHT_APP_ADJ | 400 | 运行在后台,尽量避免杀掉 |
SERVICE_ADJ | 500 | 服务进程 |
HOME_APP_ADJ | 600 | Home应用,尽量避免杀害,用户可能经常用到 |
PREVIOUS_APP_ADJ | 700 | 上一个应用,用户可能会和当前应用来回切换 |
SERVICE_B_ADJ | 800 | 服务进程,一些老的服务,很久没用 |
CACHED_APP_MIN_ADJ | 900 | 不可见的缓存进程,adj最小值 |
CACHED_APP_MAX_ADJ | 906 | 不可见的缓存进程,adj最大值 |
NATIVE_ADJ | -1000 | Native进程,不在lmkd管理范围 |
Lowmemorykiller
Lowmemorykiller(lmkd)是一种根据阈值级别触发相应力度的内存回收机制。lmkd是一个守护进程。
adj 900以上是最容易被lmkd杀掉的,系统正常运行过程中,会有许多adj 900的进程被杀,属于正常回收。 adj 0 是前台进程,优先级最高,如果出现内存泄漏的情况,系统无内存可用,lmkd可能会杀到adj为0的进程,出现前台进程闪退的现象。 adj -1000 是native进程,不在lmkd管控范围之内,即永远不会被lmkd杀掉。
更新进程优先级
每当应用程序启动以及生命周期发送变化时(进程状态发生变化),系统都会更新其adj,流程如下:

1.每当进程状态发生变化都会调用AMS.updateOomAdjLocked
2.computeOomAdjLocked:根据当前进程状态计算adj的值
3.applyOomAdjLocked:把计算后的adj更新保存到相应的进程信息中
4-11.通过socket把adj值写入到/proc/pid/oom_score_adj
调整系统优先级(客制化白名单)
为了防止部分进程因为优先级过低而被lowmemorykiller杀掉,因此需要客制化调整进程优先级。
从上图更新优先级的流程可知,客制化内容可在applyOomAdjLocked完成,即在此处判断是否是需要调整的应用的包名,确定后在重新设置adj的值。
网友评论