Google 致力于为黑人社区推动种族平等。查看具体举措

低内存终止守护进程 (lmkd)

Android 低内存终止守护进程 (lmkd) 可监控运行中的 Android 系统的内存状态,并通过终止最不必要的进程来应对内存压力较高这一问题,使系统以可接受的水平运行。

内存压力简介

并行运行多个进程的 Android 系统可能会遇到系统内存耗尽并且需要更多内存的进程出现明显延迟的情况。内存压力是系统内存不足的一种状态,它需要 Android 通过限制或终止不必要的进程、请求进程释放非关键缓存资源等方式来释放内存(以缓解压力)。

过去,Android 使用内核中的 lowmemorykiller 驱动程序来监控系统内存压力,该驱动程序是一种依赖于硬编码值的严格机制。从内核 4.12 开始,lowmemorykiller 驱动程序已从上游内核中移除,用户空间 lmkd 会执行内存监控以及进程终止任务。

用户空间 lmkd

用户空间 lmkd 可实现与内核中的驱动程序相同的功能,但它使用现有的内核机制检测和估测内存压力。这些机制包括使用内核生成的 vmpressure 事件或压力失速信息 (PSI) 监视器来获取关于内存压力级别的通知,以及使用内存 cgroup 功能限制分配给每个进程的内存资源(根据每个进程的重要性)。

终止策略

用户空间 lmkd 支持基于以下各项内容的终止策略:vmpressure 事件或 PSI 监视器、其严重性以及交换利用率等其他提示。内存不足的设备和高性能设备的终止策略有所不同:

  • 对于内存不足的设备,一般情况下,系统会选择承受较大的内存压力。
  • 对于高性能设备,如果存在内存压力,则属于异常情况,应及时修复,以免影响整体性能。

您可以使用 ro.config.low_ram 属性来配置终止策略(如需了解详情,请参阅低内存配置)。

用户空间 lmkd 还支持一种旧模式,在该模式下,它使用与内核中的 lowmemorykiller 驱动程序相同的策略(即可用内存和文件缓存阈值)做出终止决策。要启用旧模式,请将 ro.lmk.use_minfree_levels 属性设置为 true

使用用户空间 lmkd

在 Android 9 及更高版本中,用户空间 lmkd 会在未检测到内核中的 lowmemorykiller 驱动程序时激活。由于用户空间 lmkd 要求内核支持内存 cgroup,因此必须使用以下配置设置编译内核:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

压力失速信息 (PSI)

Android 10 及更高版本支持新的 lmkd 模式,它使用内核压力失速信息 (PSI) 监视器来检测内存压力。上游内核中的 PSI 补丁程序集(反向移植到 4.9 和 4.14 内核)测量由于内存不足而导致任务延迟的时间。由于这些延迟会直接影响用户体验,因此它们代表了确定内存压力严重性的便捷指标。上游内核还包括 PSI 监视器,该监视器允许特权用户空间进程(例如 lmkd)指定这些延迟的阈值,并在突破阈值时从内核订阅事件。

PSI 监视器与 vmpressure 信号

由于 vmpressure 信号(由内核生成,用于内存压力检测并由 lmkd 使用)通常包含大量误报,因此 lmkd 必须执行过滤以确定内存是否真的有压力。这会导致不必要的 lmkd 唤醒并使用额外的计算资源。使用 PSI 监视器可以实现更精确的内存压力检测,并最大限度地减少过滤开销。

使用 PSI 监视器

要使用 PSI 监视器(而不是 vmpressure 事件),请配置 ro.lmk.use_psi 属性。默认值为 true,使得 PSI 监视器成为 lmdk 内存压力检测的默认机制。由于 PSI 监视器需要内核支持,因此内核必须包含 PSI 向后移植补丁程序,并在启用 PSI 支持 (CONFIG_PSI=y) 的情况下进行编译。

配置 lmkd

使用以下属性为特定设备配置 lmkd

属性 使用 默认
ro.config.low_ram 在内存不足的设备和高性能设备之间进行选择。 false
ro.lmk.use_psi 使用 PSI 监视器(而不是 vmpressure 事件)。 true
ro.lmk.use_minfree_levels 使用可用内存和文件缓存阈值来做出进程终止决策(即匹配内核中的 lowmemorykiller 驱动程序的功能)。 false
ro.lmk.low 可在低 vmpressure 级别下被终止的进程的最低 oom_adj 得分。 1001
(已停用)
ro.lmk.medium 可在中等 vmpressure 级别下被终止的进程的最低 oom_adj 得分。 800
(已缓存或非必需服务)
ro.lmk.critical 可在临界 vmpressure 级别下被终止的进程的最低 oom_adj 得分。 0
(任何进程)
ro.lmk.critical_upgrade 能够升级到临界级别。 false
ro.lmk.upgrade_pressure 由于系统交换次数过多,将在该级别升级的 mem_pressure 上限。 100
(已停用)
ro.lmk.downgrade_pressure 由于仍有足够的可用内存,将在该级别忽略 vmpressure 事件的 mem_pressure 下限。 100
(已停用)
ro.lmk.kill_heaviest_task 终止符合条件的最重要任务(最佳决策)与任何符合条件的任务(快速决策)。 true
ro.lmk.kill_timeout_ms 从某次终止后到其他终止完成之前的持续时间(以毫秒为单位)。 0
(已停用)
ro.lmk.debug 启用 lmkd 调试日志。 false

设备配置示例:

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