在现有的技术条件下,内存永远都是一个吃紧的资源,不用说是PC上会出现内存不足的可能,更不必说在移动设备上了。一旦出现内存不足就会导致系统卡顿,影响用户体验。而Android运行在Linux的基础之上,Linux的内存的使用原则就是不要浪费内存,所以在程序退出时在一段时间内还停留在内存中,这也是我们下一次打开程序时发现快一些的原因;但是这样带来的坏处就是如果驻留在内存中的程序多了,容易导致OOM的可能。
在Linux中有一个内存监控机制OOMKiller,一旦发现内存使用进入一个临界值就会自动按照一定的策略来清理,它的核心思想是:
1 按照优先级,从低到高来杀死进程,回收内存资源
2 一方面要考虑杀死进程给系统带来的损坏要尽量小,另一方面要释放尽量多的内存
具体的做法是OOMKiller会根据一些参考因素如进程消耗内存,运行时间,OOM权重等指标计算出一个oom_score分数,这个分数越低,进程被杀死的概率越小,被杀死的时间越晚。
而对于Android系统来说是实现一个"不同级别"的killer,这个模块名称为Low Memory Killer,代码在drivers/staging/android/LowMemoryKiller.c文件中
static int __init lowmem_init(void)
{
register_shrinker(&lowmem_shrinker);
return 0;
}
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="text-align: -webkit-auto;">代码中</span><span style="text-align: -webkit-auto;">注册一个shrinker监听器,如果系统空间页面低于一定的阈值,执行这个lowmem_shrinker函数</span></span>
该文件中定义了两个重要的数组:
static int lowmem_adj[6] = {
0,
1,
6,
12,
};
static int lowmem_adj_size = 4;
static size_t lowmem_minfree[6] = {
3 * 512, /* 6MB */
2 * 1024, /* 8MB */
4 * 1024, /* 16MB */
16 * 1024, /* 64MB */
};
static int lowmem_minfree_size = 4;
上面定义的两个数组时一一对应的,其中lowmem_adj表示的是被处理某一个级别的adj的值,lowmen_minfree则表示该级别对应的内存阈值。比如说adj=0的级别,它对应的内存阈值是6M,也就是在可用内存小于6M时,会清除adj大于等于0的所有进程。所以可以看出adj越小,它被杀死的可能越小。
上面定义的是系统默认的,可以通过设置相应的文件来修改这两组值:
/sys/module/lowmemorykiller/parameters/adj
/sys/module/lowmemorykiller/parameters/minfree (以页为单位,一般是4KB大小)
在Android系统中定义了几个adj的值,他的意义分别如下:
这些是系统提供的adj,我们还可以改变自己进程的adj值,有以下两种方式:
1 写文件 写/proc/pid/oom_adj 值,在init.rc文件中就经常看到这种语句
on early-init
write /proc/1/oom_adj -16
设置init进程的adj 值为-16,属于系统进程永远不会被杀死
2 设置persistent属性。
在AndroidManifest.xml文件中设置这个属性为true,即可将其adj的值设置为-12,处于这个级别的进程基本上也不会被杀死,比如电话。