车机上的LMK优化

背景

        LMK是Android原生kernel中的一种kill应用进程的机制,其原理是当系统可用内存不足某些阈值时,开始kill一些优先级较低的进程。在某款车机上,发现该机制存在不合理的地方,如

 

 有如下几个问题:

(1)如上图所示,cache为1292476kB,实际上大于后面的524288kB,但依然还是进行了kill动作,为什么?

(2)频繁的kill动作会引发IO问题,从而影响系统性能;

(3)车机系统尽量少kill应用来使其可被快速启动;

原因分析

        该款车机是Android9.0的版本(查看kernel/msm-4.14/Makefile,kernel版本为4.14.156),依然使用的是lowmemorykiller.c的逻辑,其主要代码路径为

kernel/msm-4.14/drivers/staging/android/lowmemorykiller.c

对于该逻辑,主要有如下几个逻辑。

kill时机

        lowmemorykiller.c中通过register_shrinker(&lowmem_shrinker)和vmpressure_notifier_register(&lmk_vmpr_nb)分别注册了内存页回收的shrink事件和vmpressure的事件,因此,负责正式kill事件的lowmem_scan方法和负责kill前的若干条件判断的lmk_vmpressure_notifier方法会在Android内核进行内存回收(kswapd0进程)时就会被非常频繁的调用,但这两个方法之间仅有变量shift_adj有联系(该变量用于lowmem_scan方法中对min_score_adj的调整),执行的时机是不相关的。

static struct shrinker lowmem_shrinker = {
        .scan_objects = lowmem_scan,
        .count_objects = lowmem_count,
        .seeks = DEFAULT_SEEKS * 16
};
static struct notifier_block lmk_vmpr_nb = {
        .notifier_call = lmk_vmpressure_notifier,
};
static int __init lowmem_init(void)
{
        register_shrinker(&lowmem_shrinker);
        vmpressure_notifier_register(&lmk_vmpr_nb);
        if (register_hotmemory_notifier(&lmk_memory_callback_nb))
                lowmem_print(1, "Registering memory hotplug notifier failed\n");
        return 0;
}

        首先回答问题“cache为1292476kB,实际上大于后面的524288kB,但依然还是进行了kill动作,为什么?”,原因是这两个值与kill的逻辑并没有因果的关系,但是当内存的pressure值大于90%(内存回收的压力率),因为lowmem_scan方法的adjust_minadj会根据shift_adj对min_score_adj值进行调整,就可能出现上述看似矛盾的日志;否则LMK还是会按照上述两者的大小比较来kill。实际上,当内存的pressure值大于90%的时候,就算没有及时kill某些进程腾出内存,系统也并不会立即OOM,内核还是会通过shrink快速回收,除非遇到无法及时回收才会导致OOM。在该车机上,经常也会碰到上述矛盾的日志,就是在当时时刻系统的可用内存紧缺(/proc/vmstat中的nr_free_pages,相当于/proc/meminfo中的MemFree的值)导致内存回收的压力大于90%了。但此时的文件页(other_file,主要包含/proc/meminfo中的Cached、SwapCached和Buffers)内存可能还很多,也是大概率可以被及时回收的,此时也并不一定要立即通过LMK的kill方式腾出内存。

static void vmpressure_work_fn(struct work_struct *work)
{
        struct vmpressure *vmpr = work_to_vmpressure(work);
        unsigned long scanned;
        unsigned long reclaimed;
        unsigned long pressure;
        enum vmpressure_levels level;
        bool ancestor = false;
        bool signalled = false;

        spin_lock(&vmpr->sr_lock);
        /*
         * Several contexts might be calling vmpressure(), so it is
         * possible that the work was rescheduled again before the old
         * work context cleared the counters. In that case we will run
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值