LMKD 借助 Linux 内核的 OOM(Out of Memory)机制来管理内存。当系统内存不足时,OOM 触发器会发送信号给LMKD,通知其进行内存管理。LMKD根据预先定义的策略和优先级,选择性地终止一些进程,以释放内存。
LMKD运行流程如下:
这里选择运行到第4步时进行进程终止过滤,即使用包名进行过滤。
修改文件为: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;
- }
思考与扩展:这里实际上也可以根据自己的需要做成白名单和黑名单来解决该问题,但是其本质都是包名的过滤。