lmkd mem

tech2026-10-08  2

Android Q以后,google推荐使用lmkd,lmkd其中一种工作模式是根据内存压力去kill进程.

https://source.android.google.cn/devices/tech/perf/lmkd文档中:

mem_pressure = 内存使用量/RAM_and_swap 使用量(以百分比的形式表示)

具体到代码中:

   if ((mem_usage = get_memory_usage(&mem_usage_file_data)) < 0) {         goto do_kill;     }     if ((memsw_usage = get_memory_usage(&memsw_usage_file_data)) < 0) {         goto do_kill;     }     // Calculate percent for swappinness.     mem_pressure = (mem_usage * 100) / memsw_usage; //添加log,能够查看内存压力等级 ALOGI("mem_usage = %lld KB memsw_usage = %lld KB mem_pressure  = %lld " ,mem_usage/1024 , memsw_usage /1024,mem_pressure);     if (enable_pressure_upgrade && level != VMPRESS_LEVEL_CRITICAL) {         // We are swapping too much.         if (mem_pressure < upgrade_pressure) {             level = upgrade_level(level);             if (debug_process_killing) {                 ALOGI("Event upgraded to %s", level_name[level]);             }         }     }

可以看到

mem_pressure = (mem_usage * 100) / memsw_usage; mem_usage = get_memory_usage(&mem_usage_file_data) memsw_usage = get_memory_usage(&memsw_usage_file_data)

#define MEMCG_MEMORY_USAGE "/dev/memcg/memory.usage_in_bytes" #define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes"

从代码中看到查看到是去读取两个节点.这两个节点存储的数据的含义就是:

1.内存使用量

2.RAM_and_swap 使用量

我们具体去cat一下并且计算开机后的内存压力.

E:\02_Project>adb shell cat /dev/memcg/memory.usage_in_bytes 568688640

E:\02_Project>adb shell cat /dev/memcg/memory.memsw.usage_in_bytes 762757120

mem_pressure = 568688640*100/762757120 = 74.5

即现在样机的内存压力为74.5.

如果使用apk,那么zram会增加.mem_pressure的数值会变小.

mem_pressure的数值与以下系统属性有关.

    ro.lmk.low=1001\     ro.lmk.medium=800\     ro.lmk.critical=0\     ro.lmk.upgrade_pressure=40\     ro.lmk.downgrade_pressure=60\

从代码可以看到:

if (mem_pressure < upgrade_pressure) {             level = upgrade_level(level);             if (debug_process_killing) {                 ALOGI("Event upgraded to %s", level_name[level]);             }         }

和

 if (mem_pressure > downgrade_pressure) {             if (debug_process_killing) {                 ALOGI("Ignore %s memory pressure", level_name[level]);             }             return;         } else if (level == VMPRESS_LEVEL_CRITICAL && mem_pressure > upgrade_pressure) {             if (debug_process_killing) {                 ALOGI("Downgrade critical memory pressure");             }             // Downgrade event, since enough memory available.             level = downgrade_level(level);         }

如果 mem_pressure<40 ,内存压力等级升级. 如果 mem_pressure > 60,内存压力等级降级

压力等级为:

enum vmpressure_level {     VMPRESS_LEVEL_LOW = 0,     VMPRESS_LEVEL_MEDIUM,     VMPRESS_LEVEL_CRITICAL,     VMPRESS_LEVEL_COUNT };

其中:

level与oomadj有对应关系.

 /* By default disable low level vmpressure events */     level_oomadj[VMPRESS_LEVEL_LOW] =         property_get_int32("ro.lmk.low", OOM_SCORE_ADJ_MAX + 1);     level_oomadj[VMPRESS_LEVEL_MEDIUM] =         property_get_int32("ro.lmk.medium", 900);     level_oomadj[VMPRESS_LEVEL_CRITICAL] =         property_get_int32("ro.lmk.critical", 0);

根据我们的配置:

ro.lmk.low = 1001

ro.lmk.medium = 800 ro.lmk.critical = 0

所以

level_oomadj[VMPRESS_LEVEL_LOW] =1001 level_oomadj[VMPRESS_LEVEL_MEDIUM] =800 level_oomadj[VMPRESS_LEVEL_CRITICAL] =0

下面是kill进程

if (low_ram_device) {         /* For Go devices kill only one task */         if (find_and_kill_process(level_oomadj[level]) == 0) {             if (debug_process_killing) {                 ALOGI("Nothing to kill");             }         } else {             meminfo_log(&mi);         }     }

level_oomadj[level]=1001/800/0

这里前面计算的level的等级会转换为oom_adj=1001/800/0

 接下来会到:

 

retry:     for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) {         struct proc *procp;         while (true) {             procp = kill_heaviest_task ?                 proc_get_heaviest(i) : proc_adj_lru(i);             if (!procp)                 break;             killed_size = kill_one_process(procp, min_score_adj);             if (killed_size >= 0) { #ifdef LMKD_LOG_STATS                 if (enable_stats_log && !lmk_state_change_start) {                     lmk_state_change_start = true;                     stats_write_lmk_state_changed(log_ctx, LMK_STATE_CHANGED,                                                   LMK_STATE_CHANGE_START);                 } #endif                 break;             }         }         if (killed_size) {             break;         }     }

 

killed_size = kill_one_process(procp, min_score_adj); kill_one_process中最终会调用:

 r = kill(pid, SIGKILL);杀掉指定pid进程.

最新回复(0)