用户空间的LMKD

用户空间的LMKD

 

https://www.jianshu.com/p/1ef6e8a1c773

 

原文:https://source.android.com/devices/tech/perf/lmkd

 

本文描述了Android 9中添加的用户空间lowmemorykiller守护程序(lmkd)功能以及如何配置它们。

以前,Android使用内核lowmemorykiller驱动程序终止不必要的进程来缓解内存压力。这种机制死板且依赖于硬编码值,而且从内核4.12开始,lowmemorykiller驱动程序被排除在上游内核之外。

用户空间lmkd进程实现同样的功能,用已有的内核机制来检测和估计内存压力。它使用内核生成的vmpressure事件来获取有关内存压力级别的通知。它还可以使用内存cgroup功能根据其重要性限制分配给每个进程的内存资源。

如何切换到用户空间lmkd

从Android 9开始,如果未检测到内核中的lowmemorykiller驱动程序,则用户空间lmkd会激活。注:用户空间lmkd需要内核支持内存cgroup。因此,要切换到用户空间 lmkd,应配置以下设置编译内核:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

lmkd终止策略

lmkd同时支持新的和传统模式的终止策略,新的终止策略基于vmpressure事件,进程的重要性以及交换利用率等其他提示;传统模式的lmkd 终止策略就像内核lowmemorykiller 驱动程序那样做出终止决定。

新的终止策略因低内存和高性能设备而异。在低内存设备的情况下,系统应该比正常操作模式承受更高的内存压力; 在高性能设备上,内存压力应被视为异常情况,在影响整体性能之前应予以修复。ro.config.low_ram属性允许选择一种模式而非另一种。有关设置此属性的说明,请参阅低RAM配置

在传统模式下,lmkd根据可用内存和文件缓存阈值进行终止决策。通过将ro.lmk.use_minfree_levels 属性设置为true来启用此模式。

为特定设备配置lmkd

配置lmkd以下属性:

属性使用默认值
ro.config.low_ram在低内存和高性能设备之间进行选择。false
ro.lmk.use_minfree_levels使用空闲内存和文件缓存阈值来决定何时终止。此模式与内核lowmemorykiller驱动程序的工作方式相同。false
ro.lmk.low在低压力水平下有资格杀死的进程的最小oom_adj得分。1001(禁用)
ro.lmk.medium适合在中等压力水平下杀死的进程的最小oom_adj分数。800(缓存或非必要服务)
ro.lmk.critical有资格在关键压力水平下被杀死的进程的最小oom_adj分数。0(任何过程)
ro.lmk.critical_upgrade可以升级到关键级别。false
ro.lmk.upgrade_pressure由于系统交换太多,将升级哪个级别的最大mem_pressure。100(禁用)
ro.lmk.downgrade_pressurevmpressure事件将被忽略的最小mem_pressure *,因为仍有足够的可用内存。100(禁用)
ro.lmk.kill_heaviest_task终止最重要的合格任务(最佳决策)与任何符合条件的任务(快速决策)。true
ro.lmk.kill_timeout_ms终止后的持续时间(毫秒),不会进行额外的终止。0(禁用)
ro.lmk.debug启用lmkd调试日志。false

注: mem_pressure = RAM使用率/ RAM_and_swap使用率%

以下是一个设备配置示例:

PRODUCT_PROPERTY_OVERRIDES += \
    ro.lmk.low=1001 \
    ro.lmk.medium=800 \
    ro.lmk.critical=0 \
    ro.lmk.critical_upgrade=false \
    ro.lmk.upgrade_pressure=100 \
    ro.lmk.downgrade_pressure=100 \
    ro.lmk.kill_heaviest_task=true

 

### 关于 `lmkd` 和 `do_kill` 的实现与流程 #### 什么是 `lmkd` `lmkd` 是 Low Memory Killer Daemon 的缩写,它是 Android 系统中的一个组件,用于监控系统的内存状态,并在必要时杀死占用过多内存的进程以释放资源。其核心功能类似于 Linux 内核中的 OOM(Out Of Memory)机制[^1],但在 Android 中进行了优化和定制化。 `lmkd` 主要通过读取 `/proc/meminfo` 或其他内核暴露的信息来评估当前可用内存的状态。如果发现系统处于低内存状态,则会根据预定义的策略选择目标进程并通知内核将其终止。 #### `do_kill` 流程概述 在 Linux 内核中,`do_kill` 并不是一个独立的功能函数名,而是指代整个 OOM 杀死进程的核心逻辑的一部分。以下是基于引用描述的相关过程: 1. **OOM 触发条件** 当系统内存不足时,Linux 内核会触发 `out_of_memory()` 函数[^2]。此函数负责协调整个 OOM 处理流程。 2. **选择目标进程** 在 `out_of_memory()` 调用过程中,会选择调用 `select_bad_process()` 函数来决定哪个进程应该被杀死。该函数内部依赖于 `oom_badness()` 计算每个候选进程的“坏度”分数。通常情况下,“最坏”的进程是指那些消耗最多内存且对系统整体影响较小的进程[^1]。 3. **执行强制退出** 一旦选定目标进程,就会向它发送信号 (`SIGKILL`) 实现强制关闭操作。这相当于运行命令 `kill -9 <pid>`[^2]。 4. **具体代码路径分析** 下面展示了一个简化版伪码表示法说明上述提到的关键部分如何协作完成任务: ```c // out_of_memory() function outline void out_of_memory(gfp_t gfp_mask, int order) { struct task_struct *p; p = select_bad_process(&chosen_points); if (p && is_global_init(p)) { // 如果选中的是 init 进程则 panic oom_kill_process(p); // 否则继续尝试 kill 掉这个进程 } } // select_bad_process calls into this helper to evaluate each candidate. static unsigned long oom_badness(struct task_struct *p, const nodemask_t *nodemask) { ... } // Finally send SIGKILL signal via force_sig() void oom_kill_process(struct task_struct *victim){ force_sig(SIGKILL,victim); } ``` 以上展示了从检测到处理的一系列动作链路图解。 #### 结合 `lmkd` 的特殊场景应用 对于 Android 设备而言,由于存在多种类型的后台服务以及前台用户体验需求等因素考虑,在标准 Kernel 层面上可能无法完全满足特定平台的要求。因此引入了像 `lmkd` 那样的用户空间守护程序来进行更精细控制。例如它可以设置不同的阈值级别对应不同重要程度的应用类别;或者记录历史行为模式以便做出更加智能化决策等等[^3]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值