Android Framework 常见解决方案(22)防应用被LowMemoryKillerDaemon(LMKD)杀掉

198 篇文章 97 订阅
本文介绍了LMKD如何利用Linux内核的OOM机制进行内存管理,包括监控内存使用、计算压力指数、终止进程等步骤。重点提到在AndroidRS中,通过修改lmkd.cpp文件实现对特定包名的进程过滤,以防止不必要的内存消耗。
摘要由CSDN通过智能技术生成

1 原理说明

LMKD 借助 Linux 内核的 OOM(Out of Memory)机制来管理内存。当系统内存不足时,OOM 触发器会发送信号给LMKD,通知其进行内存管理。LMKD根据预先定义的策略和优先级,选择性地终止一些进程,以释放内存。

LMKD运行流程如下:

  1. 监测内存使用:LMKD 定期检查系统内存使用情况,包括各个进程的内存占用和系统总体内存压力。
  2. 内存压力评估:根据内存使用情况,LMKD 会计算出当前的内存压力指数,以判断是否需要进行内存管理。
  3. 内存压力事件处理:当内存压力指数超过一定阈值时,LMKD 触发内存压力事件,并根据预先配置的策略进行相应的处理。
  4. 进程终止:LMKD 根据策略和优先级,选择性地终止一些进程。通常,LMKD 会优先终止那些占用内存较多、优先级较低或者处于后台运行的进程。
  5. 释放内存:通过终止进程释放的内存会被回收,从而使系统内存得到释放,缓解内存压力。
  6. 日志记录和统计:LMKD 记录终止的进程信息和释放的内存量,并将其记录到系统日志中,以供后续分析和优化。

这里选择运行到第4步时进行进程终止过滤,即使用包名进行过滤。

2 修改方案(Android R S)

修改文件为:AOSP/system/memory/lmkd/lmkd.cpp,不同可能lmkd.cpp的位置不同,本质上都是修改kill_one_process的实现,过滤掉包名,具体代码修改如下:

static int kill_one_process(struct proc* procp, int min_oom_score, struct kill_info *ki,
                            union meminfo *mi, struct wakeup_info *wi, struct timespec *tm,
                            struct psi_data *pd) {
    int pid = procp->pid;
    int pidfd = procp->pidfd;
    uid_t uid = procp->uid;
    char *taskname;
    int r;
    int result = -1;
    struct memory_stat *mem_st;
    struct kill_stat kill_st;
    int64_t tgid;
    int64_t rss_kb;
    int64_t swap_kb;
    static char buf[PAGE_SIZE];
+    //AGS add start
+    char packageName[128] = {""};
+    //AGS add end

    if (!read_proc_status(pid, buf, sizeof(buf))) {
        goto out;
    }
    if (!parse_status_tag(buf, PROC_STATUS_TGID_FIELD, &tgid)) {
        ALOGE("Unable to parse tgid from /proc/%d/status", pid);
        goto out;
    }
    if (tgid != pid) {
        ALOGE("Possible pid reuse detected (pid %d, tgid %" PRId64 ")!", pid, tgid);
        goto out;
    }
    // Zombie processes will not have RSS / Swap fields.
    if (!parse_status_tag(buf, PROC_STATUS_RSS_FIELD, &rss_kb)) {
        goto out;
    }
    if (!parse_status_tag(buf, PROC_STATUS_SWAP_FIELD, &swap_kb)) {
        goto out;
    }

    taskname = proc_get_name(pid, buf, sizeof(buf));
    // taskname will point inside buf, do not reuse buf onwards.
    if (!taskname) {
        goto out;
    }

+    // AGS add start,添加包名过滤
+    strncpy(packageName, taskname,128);
+    //ALOGE("AGS-lmkd:packageName=%s,taskname=%s,strcmp=%d",packageName,taskname,strcmp(packageName,"com.xxx.xxx"));
+    if(!strncmp(packageName,"com.xxx.xxx",strlen("com.xxx.xxx")))
+    {
+        ALOGE("AGS add lmkd-whitelist:pkgname=%s",packageName);
+        return -1000;
+    }
+    //AGS add end

    mem_st = stats_read_memory_stat(per_app_memcg, pid, uid, rss_kb * 1024, swap_kb * 1024);
    //...
out:
    /*
     * WARNING: After pid_remove() procp is freed and can't be used!
     * Therefore placed at the end of the function.
     */
    pid_remove(pid);
    return result;
}

思考与扩展:这里实际上也可以根据自己的需要做成白名单和黑名单来解决该问题,但是其本质都是包名的过滤。

评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值