LMK 工作机制

【Android】LMK 工作机制

Android分析之LowMemoryKiller

 

 

Android Kernel 会定时执行一次检查,杀死一些进程,释放掉内存。

    那么,如何来判断,那些进程是需要杀死的呢?答案就是我们的标题:Low memory killer机制。

 

Low memory killer 则是定时进行检查。

Low memory killer 主要是通过进程的oom_adj 来判定进程的重要程度。这个值越小,程序越重要,被杀的可能性越低。

oom_adj的大小和进程的类型以及进程被调度的次序有关。

Low memory killer 的具体实现可参看:kernel/drivers/misc/lowmemorykiller.c 

1.oom_adj的值是如何赋予的

 

进程的类型,可以在ActivityManagerService中清楚的看到: 

    static final int EMPTY_APP_ADJ;

    static final int HIDDEN_APP_MAX_ADJ;

    static final int HIDDEN_APP_MIN_ADJ;

    static final int HOME_APP_ADJ;

    static final int BACKUP_APP_ADJ;

    static final int SECONDARY_SERVER_ADJ;

    static final int HEAVY_WEIGHT_APP_ADJ;

    static final int PERCEPTIBLE_APP_ADJ;

    static final int VISIBLE_APP_ADJ;

    static final int FOREGROUND_APP_ADJ;

    static final int CORE_SERVER_ADJ = -12;

    static final int SYSTEM_ADJ = -16; 

   ActivityManagerService定义各种进程的oom_adj,CORE_SERVER_ADJ代表一些核心的服务的omm_adj,数值为-12,这类进程永远也不会被杀死。

其他未赋值的都在static块中进行了初始化,是通过system/rootdir/init.rc进行配置的:

 

init.rc中:

 

# Define the oom_adj values for the classes of processes that can be

# killed by the kernel.  These are used in ActivityManagerService.

   setprop ro.FOREGROUND_APP_ADJ 0

   setprop ro.VISIBLE_APP_ADJ 1

   setprop ro.SECONDARY_SERVER_ADJ 2

   setprop ro.HIDDEN_APP_MIN_ADJ 7

   setprop ro.CONTENT_PROVIDER_ADJ 14

   setprop ro.EMPTY_APP_ADJ 15

 

# Define the memory thresholds at which the above process classes will

# be killed.  These numbers are in pages (4k).

   setprop ro.FOREGROUND_APP_MEM 1536

   setprop ro.VISIBLE_APP_MEM 2048

   setprop ro.SECONDARY_SERVER_MEM 4096

   setprop ro.HIDDEN_APP_MEM 5120

   setprop ro.CONTENT_PROVIDER_MEM 5632

   setprop ro.EMPTY_APP_MEM 6144

 

配置文件有如下两个:

/sys/module/lowmemorykiller/parameters/adj

/sys/module/lowmemorykiller /parameters/minfree

owmeme_adj中各项数值代表阈值的警戒级数,

lowmem_minfree代表对应级数的剩余内存。

adj文件存放着oom_adj 内存警戒值( 以4K为单位)
 
0 1536 
1 2048 
2 4096 
7 5120 
14 5632 
15 6144

 

 

也就是说,当系统的剩余内存为小于6MB时候,警戒级数为0,当系统内存剩余小于8M而大于
6M的时候,警戒级数为1,当内存小于64M大于16MB的时候,警戒级数为12.

 

 

对于某些小内存设备,我们可以调整对应的门限值,例如:
一般调整后三个值。
echo “1536,2048,4096,15360,17920,20480″>/sys/module/lowmemorykiller/parameters/minfree

 

原文作者:AndyTsui

原文链接:http://blog.youkuaiyun.com/AndyTsui/archive/2011/02/27/6210653.aspx

2.LMK的工作机制

 
LMK开始工作时,
首先根据阈值表确定当前的警戒级数,则高于警戒级数的进程是待杀的范围。
然后遍历所有进程的oom_adj值,找到大于min_adj的进程,若找到多个,则把占用进程最大的进程存放在selected中。
 
最关键的一步就是,发送SIGKILL信息,杀掉该进程。
 

3.tips

 
(1)在init.rc中配置:
# Write value must be consistent with the above properties.
   write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15
 
   write /proc/sys/vm/overcommit_memory 1
   write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144
 
   class_start default
 
   

(2)进程oom_adj同样可以进行设置,通过write /proc/<PID>/oom_adj  ,在init.rc中,init进程的pid1omm_adj被配置为-16,永远不会被杀死。

   # Set init its forked children's oom_adj.
   write /proc/1/oom_adj -16
(3)dumpsys activity可以dump进程的信息,查看adj值
   procrank可以查看进程占用内存大小

from: http://www.cnblogs.com/rayray/p/3413688.html
<think>嗯,用户想了解thrashing_limit在Android或Linux系统中的LMK配置问题。这个问题涉及系统级内存管理机制,需要仔细梳理。从用户提问看,ta应该是有Android系统开发背景的技术人员,或者是对系统底层机制感兴趣的开发者。thrashing_limit是个相当专业的参数,普通用户不会接触到,说明用户在做内存优化相关的工作。我注意到引用内容主要来自Android源码文档,其中引用[1]详细描述了thrashing_limit的衰减机制:当发生内存抖动时,系统会通过百分比衰减(thrashing_limit_decay_pct)逐步降低thrashing_limit阈值。引用[3]则提供了具体的配置参数示例,包括70ms的PSI部分停滞阈值和100的thrashing_limit初始值。引用[4]补充了Linux调度统计信息,这些对诊断内存抖动有帮助。用户可能真正想解决的是设备频繁杀进程的问题。thrashing_limit本质上是个防抖动的安全阀:当页面回收量持续超过这个阈值,LMKD就会介入杀进程。但设置太高会导致响应延迟,太低又会过度杀进程。引用[3]提到的ro.lmk.thrashing_limit_decay属性很关键,它控制着每次干预后的阈值衰减幅度。需要重点解释清楚的是PSI机制与thrashing_limit的联动关系。从引用[2][3]看,现代Android已用PSI替代vmpressure作为主要监控手段。当PSI事件触发且连续1秒内回收页数超过thrashing_limit时,就会启动查杀流程,查杀后立即按百分比衰减阈值——这个设计是为了快速打破抖动循环。对于配置实践,应该强调三点:初始值建议100(如引用[3]),但实际需用tracepoint验证;调试时要同时关注PSI事件延迟参数;修改后必须用procstats监控杀进程日志。用户如果遇到特定设备的OOM问题,可能需要结合lowmem.minfree参数调整。</think>以下是关于 `thrashing_limit` 在 Android/Linux LMK(Low Memory Killer)机制中的作用和配置详解: --- ### **thrashing_limit 的作用** `thrashing_limit` 是 Android 低内存查杀(LMKD)中的关键参数,用于**控制内存抖动(thrashing)的容忍阈值**。其核心逻辑为: 1. **定义抖动** 当系统在 **1秒内回收的页面数**(`pages_freed`)超过 `thrashing_limit` 时,判定发生内存抖动。 2. **触发查杀** 此时 LMKD 会主动查杀进程以释放内存(`find_and_kill_process()`)。 3. **动态衰减** 每次查杀后,`thrashing_limit` 按比例衰减(见公式): $$ \text{thrashing\_limit} = \frac{\text{thrashing\_limit} \times (100 - \text{decay\_pct})}{100} $$ 通过逐步降低阈值,迫使系统更快抑制抖动[^1][^3]。 --- ### **配置方法(Android 系统)** #### **1. 系统属性配置** 在设备配置文件(如 `system.prop`)中添加以下属性: ```properties # 启用 PSI 监控(需关闭 vmpressure) ro.lmk.use_psi=true # 设置初始抖动阈值(默认 100 页/秒) ro.lmk.thrashing_limit=100 # 设置阈值衰减比例(默认 10%) ro.lmk.thrashing_limit_decay=10 # PSI 事件敏感度(部分停滞/完全停滞) ro.lmk.psi_partial_stall_ms=70 ro.lmk.psi_complete_stall_ms=700 ``` **说明**: - `thrashing_limit` 单位:**页/秒**(通常 1页=4KB)。 - `thrashing_limit_decay` 建议范围:`5-20`(百分比)[^3]。 #### **2. 动态调试(无需编译)** ```bash # 修改系统属性 adb root adb remount adb shell "setprop ro.lmk.thrashing_limit 80" # 调整阈值 adb shell "setprop ro.lmk.thrashing_limit_decay 15" # 调整衰减率 # 重启 lmkd 生效 adb shell "stop lmkd && start lmkd" ``` #### **3. 监控与验证** - **查看日志**: ```bash adb logcat | grep "lmkd" ``` 关注 `pages_freed > thrashing_limit` 及 `thrashing_limit decayed` 日志。 - **PSI 指标**: 通过 `/proc/pressure/memory` 监控内存压力事件。 --- ### **与 Linux 系统的关联** Linux 内核通过 **PSI(Pressure Stall Information)** 机制LMKD 提供内存压力数据: 1. **PSI 事件触发** 当内存部分停滞时间超过 `psi_partial_stall_ms`(如 70ms),LMKD 启动抖动检测。 2. **抖动统计依赖** `thrashing_limit` 依赖 `struct thrash_stat` 中的 `thrashing_count` 和 `delay_total`(见引用[4])。 3. **内核依赖项** 需启用配置: `CONFIG_PSI=y`, `CONFIG_SCHED_INFO=y`, `CONFIG_TASK_DELAY_ACCT=y`[^4]. --- ### **调优建议** 1. **高内存设备** 提高 `thrashing_limit`(如 150),减少过度查杀。 2. **频繁抖动场景** 降低初始阈值(如 80)并增大衰减率(如 20%),加速稳定内存。 3. **调试工具** 使用 `getdelays` 工具分析任务延迟(引用[4]): ```bash ./getdelays -t <PID> -d # 查看 thrashing 延迟 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值