linux oom内存门限,Android Low Memory Killer介绍

Linux操作系统的传统理念就是内存用的越多越好,尽可能拿来用,既然被尽量的使用,自然应该有清除机制。Android以Linux为基础,自然部分继承了这个特性。

Android使用lowmemorykiller在达到某个内存门限的情况下去选择进程删除来释放内存。

关键的配置文件有两个:

/sys/module/lowmemorykiller/parameters/adj和

/sys/module/lowmemorykiller/parameters/minfree,

配置系统的相关参数。

adj文件包含oom_adj队列,当对应的minfree值达到,则进程的oom_adj如果大于这个值

将被杀掉。

minfree包含对应oom_adj的警戒值。

参考如下:

oom_adj     内存警戒值( 以4K为单位)

0                   1536

1                   2048

2                   4096

7                   5120

14                 5632

15                 6144

基本原理:

Android的Low Memory Killer是在标准linux kernel的OOM基础上修改而来的一种内存管理机制,当系统内存不足时,杀死Bad进程释放其内存。Bad进程的选择标准有两个:oom_adj和占用内存的大小。oom_adj代表进程的优先级,数值越大,优先级越高,对应每个oom_adj都有一个空闲内存的阈值。Android Kernel每隔一段时间会检查当前空闲内存是否低于某个阈值,如果是,则杀死oom_adj最大的Bad进程,如果有两个以上Bad进程oom_adj相同,则杀死其中占用内存最多的进程。

Low Memory Killer与OOM的区别

OOM即Out of Memory是标准linux Kernel的一种内存管理机制,Low Memory Killer在它基础上作了改进:

OOM基于多个标准给每个进程打分,分最高的进程将被杀死;Low MemoryKiller则用oom_adj和占用内存的大小来选择Bad进程,OOM在内存分配不足时调用,而Low Memory Killer每隔一段时间就会检查,一旦发现空闲内存低于某个阈值,则杀死Bad进程。

Low Memory Killer的实现

Low Memory Killer的源代码在drivers/staging/android/lowmemorykiller.c中,它是通过注册Cache Shrinker来实现的。Cache Shrinker是标准linux kernel回收内存页面的一种机制,它由内核线程kswapd监控,当空闲内存页面不足时,kswapd会调用注册的Shrinker回调函数,来回收内存页面。

Low Memory Killer是在模块初始化时注册Cache Shrinker的,代码如下:

static int__init lowmem_init(void)

{

register_shrinker(&lowmem_shrinker);//注册Cache Shrinker

return 0;

}

lowmem_shrinker的定义如下:

static struct shrinker lowmem_shrinker=

{

.shrink=lowmem_shrink,

.seeks=DEFAULT_SEEKS*16

};

register_shrinker会将lowmem_shrink加入Shrinker List中,被kswapd在遍历Shrinker List时调用,而Low Memory Killer的功能就是在lowmem_shrink中实现的。

lowmem_shrink用两个数组作为选择Bad进程的依据,这两个数组的定义如下:

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

};

lowmem_minfree保存空闲内存的阈值,单位是一个页面4K,lowmem_adj保存每个阈值对应的优先级。lowmem_shrink首先计算当前空闲内存的大小,如果小于某个阈值,则以该阈值对应的优先级为基准,遍历各个进程,计算每个进程占用内存的大小,找出优先级大于基准优先级的进程,在这些进程中选择优先级最大的杀死,如果优先级相同,则选择占用内存最多的进程。

lowmem_shrink杀死进程的方法是向进程发送一个不可以忽略或阻塞的SIGKILL信号:

force_sig(SIGKILL,selected);

用户接口

设置空闲内存阈值的接口:/sys/module/lowmemorykiller/parameters/minfree;

设置对应优先级的接口:/sys/module/lowmemorykiller/parameters/adj;

设置各个进程优先级的接口:/proc//oom_adj;

Android启动时读取的配置文件system/core/rootdir/init.rc中定义了相应的属性供AP使用

并有设置这些参数:

# Define the oom_adj values for the classes of processes that can be

# killed by the kernel.  These are used in ActivityManagerService.

setprop ro.FOREGROUND_APP_ADJ 0

setprop ro.VISIBLE_APP_ADJ 1

setprop ro.SECONDARY_SERVER_ADJ 2

setprop ro.BACKUP_APP_ADJ 2

setprop ro.HOME_APP_ADJ 4

setprop ro.HIDDEN_APP_MIN_ADJ 7

setprop ro.CONTENT_PROVIDER_ADJ 14

setprop ro.EMPTY_APP_ADJ 15

#Define the memory thresholds at which the above process classes will

#be killed.These numbers are in pages(4k).

setprop ro.FOREGROUND_APP_MEM 1536

setprop ro.VISIBLE_APP_MEM 2048

setprop ro.SECONDARY_SERVER_MEM 4096

setprop ro.BACKUP_APP_MEM 4096

setprop ro.HOME_APP_MEM 4096

setprop ro.HIDDEN_APP_MEM 5120

setprop ro.CONTENT_PROVIDER_MEM 5632

setprop ro.EMPTY_APP_MEM 6144

# Write value must be consistent with the above properties.

# Note that the driver only supports 6 slots, so we have HOME_APP at the

# same memory level as services.

write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15

write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144

# Set init its forked children's oom_adj.

write /proc/1/oom_adj -16

从以上设置可以看出,将init进程oom_adj设置为-16,从而保证init进程永远不会被杀掉

实际上在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

中定义了两个更高的优先级。

// This is a process running a core server, such as telephony. Definitely

// don't want to kill it, but doing so is not completely fatal.

static final int CORE_SERVER_ADJ = -12;

// The system process runs at the default adjustment.

static final int SYSTEM_ADJ = -16;

根据以上分析,对于某些小内存设备,我们可以调整对应的门限值,例如:

一般调整后三个值。

echo "1536,2048,4096,15360,17920,20480" > /sys/module/lowmemorykiller/parameters/minfree

本篇文章来源于 Linux公社网站(www.linuxidc.com)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值