shrinker Android LowMemoryKiller原理分析(下)

(点击上面微信官方账号快速关注)
链接:http://android.jobbole.com/84953/

从正文继续
第3.8节
Use _ inkernel _ interface此值应逐步采用用户间空策略。但是,它仍然使用_ inkernel _ interface = 1,并且有:
LMK _ PROCRIO:send/proc/
LMK _ procuremove:什么都不做,直接返回;
LMK_TARGET:将相应的信息分别写入/sys/module/low memorykiller/parameters目录中的minfree和adj节点;
四.核心层
lowmemorykiller驱动位于drivers/staging/Android/low memory killer . c。
4.1 lowmemorykiller初始化
staticstructshrinker low mem _ shrinker = {
。scan_objects= lowmem_scan,
。count_objects= lowmem_count,
。seeks= DEFAULT_SEEKS* 16
};
static int _ _ init low mem _ init(void)
{
register _ shrinker(& amp;low mem _ shrinker);
返回0;
}
static void _ _ exit low mem _ exit(void)
{
注销_ shrinker(& amp;low mem _ shrinker);
}
module _ init(low mem _ init);
module _ exit(low mem _ exit);
分别使用register_shrinker和unregister_shrinker进行初始化和退出。
4.2收缩器
LMK驱动程序是通过注册shrinker实现的,这是linux内核标准中回收内存页面的一种机制,由内核线程kswapd监控。
当内存不足时,kswapd线程将遍历收缩器链表,并回调已注册的收缩器函数来回收内存页面。kswapd也会定期唤醒以执行内存操作。每个区维护active_list和inactive_list链表,内核根据页面的活动状态在这两个链表之间移动页面,最后通过shrink_slab和shrink_zone回收内存页面。如果有兴趣进一步了解linux的内存回收机制,可以自己研究一下,然后再回到LowMemoryKiller的流程分析。
4.3低内存_计数
staticunsignedlonglow mem _ count(structshrinker * s,
structshrink_control*sc)
{
returnglobal _ page _ state(NR _ ACTIVE _ ANON)+
global _ page _ state(NR _ ACTIVE _ FILE)+
global _ page _ state(NR _ INACTIVE _ ANON)+
global _ page _ state(NR _ INACTIVE _ FILE);
}
ANON代表匿名映射,没有后备存储;FILE代表文件映射;内存计算公式=活动匿名内存+活动文件内存+非活动匿名内存+非活动文件内存
4.4 lowmem_scan
触发lmkd时,先杀死oom_adj最大的进程,oom_adj相等时,选择oom_score_adj最大的进程。
staticunsignedlonglow mem _ scan(struct shrinker * s,structshrink_control*sc)
{
structtask _ struct * tsk
structtask _ struct * selected = NULL
unsignedlongrem = 0;
inttasksize
inti
short min _ SCORE _ adj = OOM _ SCORE _ ADJ _ MAX+1;
int minfree = 0;
int selected _ tasksize = 0;
shortselected _ oom _ score _ adj
int ARRAY _ SiZe = ARRAY _ SiZe(low mem _ adj);
//获取当前剩余的内存大小
into ther _ FREE = global _ page _ state(NR _ FREE _ PAGES)-total reserve _ PAGES;
into ther _ FILE = global _ page _ state(NR _ FILE _ PAGES)-
global_page_state(NR_SHMEM)-
total _ swap cache _ pages();
//获取数组大小
if(low mem _ adj _ size & lt;数组大小)
array _ size = lowmem _ adj _ size
if(low mem _ min free _ size & lt;数组大小)
array _ size = low mem _ min free _ size;
//遍历lowmem_minfree数组找到对应的最小adj值
for(I = 0;i&lt。array _ sizei++){
min free = low mem _ min free[I];
if(其他_免费& ltminfree&amp。& amp其他文件&lt。minfree){
min _ score _ adj = low mem _ adj[I];
打破;
}
}
if(min _ SCORE _ adj = = OOM _ SCORE _ ADJ _ MAX+1){
返回0;
}
selected _ oom _ score _ adj = min _ score _ adj;
rcu _ read _ lock();
for_each_process(tsk){
struct task _ struct * p;
shortoom _ score _ adj
if(tsk->;旗帜和旗帜。PF_KTHREAD)
继续;
p = find _ lock _ task _ mm(tsk);

推荐阅读