Android进程内存管理-lowmemorykiller

本文详细介绍了Android系统中的低内存杀手(lowmemorykiller)机制,包括oom_adj和oom_score_adj的关系、Linux内核的oom killer与Android的lowmemorykiller的区别、minfree和adj的设置,以及Android系统如何通过AMS和lmkd共同维护app进程的管理。内容涵盖进程的内存评分、清理策略以及相关API的使用。
摘要由CSDN通过智能技术生成

Lmk

oom_adj 和oom_score_adj

都是打分因子,表示被杀的得分情况, 得分越高,越容易被杀。

  • oom_adj
    取值范围是-17至15, 取值为-17 的进程永远不会被杀。
  • oom_score_adj
    取值-1000至1000,取值-1000 的进程不会被杀。
  • oom_adj 和oom_score_adj 的关系
    内核中使用oom_score_adj, 位于task.signal.oom_score_adj字段中。那么
    oom_adj 有什么用呢?当写入oom_adj 时会被换算为oom_score_adj。
    公式如下: oom_score_adj = oom_adj *1000/17.
    其实就是直接线性映射。
  • 设置oom_adj 后,一定会生效吗?
    如果oom_adj 换算成的oom_score_adj 比当前的低,也就是降低被杀的可能性,那么需要权限,如果没权限,则返回error;权限检查通过才会生效。
  • 有权限设置oom_adj 后,再获取oom_adj,为什么值和设置的不一样?
    oom_adj = oom_score_adj * 17/1000; 和当时换算时是相反的操作,由于oom_adj 取值-17 到15, 不是17的整数倍,那么算下来肯定会少1.

linux oomkiller 和Android lowmemorykiller

linux 内核有oom killer机制,是内存管理模块在内存资源短缺时触发的内存释放操作,将一些oom_score_adj 比较高的进程杀了释放内存。
Android 中还引入了一个lowmemorykiller机制,原理也是通过类似的打分机制,和oomkiller的区别时,oomkiller是等系统内存紧张,实在没多少内存分配时才触发;而lowmemorykiller是 内存低于某个阈值就触发。

minfree 和adj

/sys/module/lowmemorykiller/parameters/minfree
18432, 23040, 27648, 32256, 55296, 80640
/sys/module/lowmemorykiller/parameters/adj
0, 100, 200, 300, 900, 906
表示内存低于80640 时,就杀死oom_score_adj 大于906的进程。

static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
{
   
    ...
    // 获取当前系统剩余内存,以page为单位
    int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
    int other_file = global_page_state(NR_FILE_PAGES) -
                                     global_page_state(NR_SHMEM);
    
    for (i = 0; i < array_size; i++) {
   
        if (other_free < lowmem_minfree[i] &&
            other_file < lowmem_minfree[i]) {
   
                min_score_adj = lowmem_adj[i];
                break;
        }
    }
    ...
    
    selected_oom_score_adj = min_score_adj;
    rcu_read_lock();
    // 遍历所有进程PCB
    for_each_process(tsk) {
   
        struct task_struct *p;
        int oom_score_adj;
        if (tsk->flags & PF_KTHREAD)
                continue;
        p = find_lock_task_mm(tsk);
        ...
        oom_score_adj = p->signal->oom_score_adj;
        if (oom_score_adj < min_score_adj) {
   
                task_unlock(p);
                continue;
        }
        
        tasksize = get_mm_rss(p->mm);
        task_unlock(p);
        if (tasksize <= 0)
                continue;
        if (selected) {
   
            // 检查优先级是否更低
            if (oom_score_adj < selected_oom_score_adj)
                    continue;
            // 如果平级,查看是否占用更多内存
            if (oom_score_adj == selected_oom_score_adj &&
                tasksize <= selected_tasksize)
                    continue;
        }
        // 选中该进程
        // 如果后续没有优先级更低或者占用内存更多的内存的平级进程的话,会将该进程杀死
        selected = p;
        ...
    }
    
    if (selected) {
   
        // 发送信号进行查杀
        send_sig(SIGKILL, selected, 0);
    }
    return rem;
}

参考: https://zhuanlan.zhihu.com/p/145245419

Android lmkd 和AMS 共同维护app进程的管理

所有的APP进程都是从zygote进程fork出来的,包装成ProcessRecord记录在system_server进程的AMS的mLruProcess列表中,由AMS统一管理。
AMS 根据app的状态(前台,后台等等),更新app进程的状态,并更新进程的oom_adj,这个值会通过socket传递给lmkd进程。

lmkd

init进程fork的一个用户空间进程,方便用户空间动态调整进程的oom_score_adj 值,从而动态控制低内存时被回收的进程; 调整minfree 和adj来动态调整查杀阈值。

FWK定义的一些进程的oom_score_adj

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ProcessList.java#69

ProcessList 中的一些常量。
// GB: 2048,3072,4096,6144,7168,8192
// HC: 8192,10240,12288,14336,16384,20480

ProcessList设置oom_adj

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ProcessList.java#69

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值