先说明一下Linux OOMKiller,再介绍基于此的Android的Low Memory Killer.
Linux底层内核有自己的内存监控机制,即OOMKiller。一旦发现系统的可用内存达到临界值,他就会跳出来,按照一定的策略,杀进程,回收内存。
进程在LINUX系统中,会有一个权重值,这个权重值存储在/proc/
进程的打分保存在/proc/
oom_adj的取值范围是-17~15, 取值-17表示OOM对此进程禁用,很多系统进程都是该值。
oom_socre_adj的取值范围是-1000~1000,-1000表示OOM对此进程禁用。
那么oom_adj是怎么转换为oom_socre_adj的呢?
查看./drivers/staging/android/lowmemorykiller.c,有如下函数:
#defineOOM_ADJUST_MAX 15
#defineOOM_SCORE_ADJ_MAX 1000
#defineOOM_SCORE_ADJ_MAX 1000
#defineOOM_DISABLE (-17)
static short lowmem_oom_adj_to_oom_score_adj(short oom_adj)
{
if (oom_adj == OOM_ADJUST_MAX)
return OOM_SCORE_ADJ_MAX;
else
return (oom_adj * OOM_SCORE_ADJ_MAX) /-OOM_DISABLE;
}
可以看出,在不考虑其他因素的情况下,当oom_adj等于最大值15的时候,oom_socre_adj也等于最大值1000,其他情况下oom_score_adj=oom_adj * 1000/17
Linux的OOMKiller存在一个问题,也就是只有在系统资源,几乎被耗尽的时候,才会触发,为此android实现了不同梯级的Killer。
梯级配置保存在手机如下两个文件中,最多可配置6个梯级(可以在init.rc中用write命令改写):
/sys/module/lowmemorykiller/parameters/adj
sys/module/lowmemorykiller/parameters/minfree
下面以一个具体示例说明:
root@shamu:/sys/module/lowmemorykiller/parameters # cat adj
0,58,117,176,529,1000
at minfree
18432,23040,27648,32256,36864,46080
root@shamu:/sys/module/lowmemorykiller/parameters #
minfree文件中配置的单位是页(1页=4KB),上面的配置含义是:
当系统内存少于46080*4KB时,所有oom_socre_adj>=1000的进程都会被杀死;
当系统内存少于36864*4KB时,所有oom_socre_adj>=529的进程都会被杀死;
当系统内存少于32256*4KB时,所有oom_socre_adj>=176的进程都会被杀死;
依次类推。。。。。
Andorid对于各种进程给予的oom_adj的值如下表:
(注:这些值定义在com.android.server.am.ProcessList中)
CACHED_APP_MAX_ADJ=15 CACHED_APP_MIN_ADJ=9 |
当前只运行了不可见的Activity组件的进程 |
SERVICE_B_ADJ=8 |
位于B列表的服务进程的OOM_ADJ值。位于B列表的都是一些旧的、过时的服务进程。 |
PREVIOUS_APP_ADJ=7 |
用户前一次交互的进程 |
HOME_ADD_ADJ=6 |
Launcher进程 |
SERVICE_ADJ=5 |
当前运行了应用Serivice进程 |
BACKUP_APP_ADJ=3 |
用于承载backup相关操作的进程 |
HEAVY_WEIFHT_APP_ADJ=4 |
重量级应用程序进程 |
PRECEPTIBLE_APP_ADJ=3 |
这类进程能够被用户感知但不可见,如后台运行的音乐播放器 |
VISABLE_APP_ADJ=1 |
前台可见的Activity进程 |
FOREGOURND_APP_ADJ=0 |
当前正在前台运行的进程,也就是用户正在交互的那个程序 |
PERSISTENT_PROC_ADJ = -12 |
Persistent性质的进程,如telephony |
SYSTEM_ADJ = -16 |
系统进程 |
看下面一段内核日志下,反复有如下打印:
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj s name
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 1] 0 1 1406 286 5 96 -1000 S init
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 304] 0 304 1085 183 5 67 -1000 S ueventd
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 306] 0 306 678 72 4 18 -1000 S oeminfo_nvm_ser
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 353] 1036 353 9702 5714 22 240 -1000 S logd
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 354] 0 354 14366 265 29 276 -1000 S vold
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 364] 0 364 1070 107 5 13 -1000 S healthd
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 365] 0 365 1924 401 7 73 -1000 S lmkd
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 366] 1000 366 1520 189 6 48 -1000 S servicemanager
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 367] 1000 367 99011 2090 103 1045 -1000 S surfaceflinger
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 368] 1000 368 28658 636 49 1190 -1000 S perfhub
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 369] 0 369 6578 395 15 79 -1000 S teecd
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 372] 1000 372 1872 306 7 100 -1000 S powerlogd
省略部分打印。。。。。。。
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 7330] 1010042 7330 482723 7981 150 9626 294 S i.motionservice
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 7682] 1010005 7682 486566 10393 162 9557 294 S d.process.acore
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 7966] 1000 7966 491435 9077 170 9615 294 S com.huawei.hidp
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 8052] 1010050 8052 482349 9825 150 9601 117 S m.huawei.secime
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 8100] 1010085 8100 371501 9810 167 5504 294 S nt.mobileqq:MSF
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 8465] 10000 8465 482993 9802 146 9685 294 S map.android.ams
[pid:25146,cpu0,kworker/0:0]lowmem_dbg:[ 8647] 1010085 8647 365707 8994 143 5556 529 S encent.mobileqq
[pid:25146,cpu0,kworker/0:0]ksm:130 60122 777 14202 7678 37465
[pid:129,cpu1,kswapd0]lowmemorykiller:Killing 'encent.mobileqq' (8647), tgid=8647, adj 529,
01-08 15:35:08.346<6>[33751.961303s] to free35976kB on behalf of 'kswapd0' (129) because
01-08 15:35:08.346<6>[33751.961303s] cache 203152kBis below limit 221184kB for oom_score_adj 529
01-08 15:35:08.346<6>[33751.961303s] Free memory is30484kB above reserved
01-08 15:35:08.965<6>[33752.579437s][2016:01:0815:35:08][pid:213,cpu0,kworker/0:1H]watchdog watchdog0: watchdog kick now
系统在反复触发LowmemoryKiller,不断的满足阶梯5或6的条件,不断的去干掉oom_socre_adj>=529或oom_socre_adj>=1000的进程。