Android Low Memory Killer

先说明一下Linux OOMKiller,再介绍基于此的Android的Low Memory Killer.


 Linux底层内核有自己的内存监控机制,即OOMKiller。一旦发现系统的可用内存达到临界值,他就会跳出来,按照一定的策略,杀进程,回收内存。

 

进程在LINUX系统中,会有一个权重值,这个权重值存储在/proc//oom_adj,系统会根据该值,同时考虑一些其他因素(如进程的内存占用量、占用CPU时间等),实时给进程打分。分越高,OOMKiller跳出来时,就越可能将其干掉。

进程的打分保存在/proc//oom_score_adj中。

 

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的进程。

 

 

你可能感兴趣的:(Android)