进程内存守护程序

Android 17 及更高版本支持进程内存守护程序 (PMGD),该守护程序通过主动按进程管理内存用量来保护系统运行状况和用户体验。 该守护程序通过对特定目标进程强制执行内存上限,验证隔离的内存泄漏或峰值不会导致系统范围内的性能下降,从而提高设备的整体稳定性。

传统的全局低内存终止程序仅在整个系统承受压力时才会运行,而 PMGD 采用的是精细化方法。该守护程序通过监控目标进程的控制组 v2 内存值来实现此目的。当目标进程超出其配置的内存限制时,pmgd 会通过记录 Statsd 内存原子来处理违规行为,然后再终止该进程。

运作方式

该守护程序使用 inotify 来侦听内存压力事件(特别是使用 memory.events 的高内存活动)。当受监控的进程触发内存事件时,pmgd 会执行以下操作:

  1. 匿名内存检查: 评估进程的匿名内存。如果超出配置的 anon_limit_in_mbpmgd 会立即终止该进程。
  2. 回收等待期: 如果匿名内存低于指定的匿名内存限制,pmgd 会等待系统回收宽限期 (reclaim_wait_time_secs)。
  3. 回收后的内存评估: 如果在宽限期过后,目标进程的 memory.current 仍大于或等于 memory.high,或者匿名内存超出 anon_limit_in_mbpmgd 会立即终止该进程。

此操作会持续执行,直到进程被终止,或者对进程进行回收使其内存用量低于指定的内存限制。

系统运行状况功能

  • 重启速率限制: 为防止启动循环或持续崩溃, pmgd 会在 /data/misc/pmgd/history.json 中跟踪进程终止情况。该守护程序将进程限制为每个设备重启一次 pmgd 启动的终止。

SELinux 配置

PMGD 监控进程的能力受 SELinux 政策的限制。如果您将 PMGD 配置为监控政策不允许其监控的进程(例如供应商特定的系统进程),PMGD 将无法监控该进程,并且您可能会在 logcat 中看到 SELinux 拒绝。

如需允许 PMGD 监控其他网域中的进程,您必须通过更新 PMGD 的设备专用 SELinux 政策来扩展 PMGD 的权限。

以下示例 device/<vendor>/<device>/sepolicy/pmgd.te 文件 添加了对新网域的访问权限:

# Allow pmgd to access vendor_system_apps
r_dir_file(pmgd, vendor_system_apps)

如需详细了解如何编写设备专用政策,请参阅 实现 SELinux

供应商定义的配置

PMGD 配置由供应商驱动,通过必需的 JSON 文件 /vendor/etc/pmgd/config.json 进行配置。此文件列出了要跟踪的进程、 其配置的内存限制配置文件(使用 控制组任务配置文件) 以及以兆字节为单位的硬匿名内存限制。

供应商配置字段

提供的 JSON 配置是进程及其限制的列表,由以下字段定义:

字段 类型 是否必需 说明 默认
target_cmd 字符串 要监控的目标进程的命令名称,例如 system_server 不适用
uid 整数 进程的用户 ID (UID)。如果省略,pmgd 会将该规则全局应用于与 target_cmd 匹配的任何进程。 不适用
reclaim_wait_time_secs 整数 在再次评估内存限制之前,等待系统回收内存的宽限期(以秒为单位) 。 5
mem_limit_profile 字符串 用于设置 控制组任务配置文件 的名称,此名称用于设置 `memory.high`。此名称用于设置进程内存限制。 不适用
anon_limit_in_mb 整数 最终匿名内存限制(以兆字节为单位)。如果匿名内存 利用率超过此值,pmgd会立即终止该 进程。 不适用
additional_task_profiles 字符串列表 `pmgd` 在监控开始时应用于进程的任何其他任务配置文件的列表。pmgd 空白列表

以下是 vendor/etc/task_profiles.json 中控制组任务配置文件的示例配置:

{
  "Attributes": [
    ...
    {
      "Name": "MemHigh",
      "Controller": "memory",
      "File": "memory.high"
    }
  ],
  "Profiles": [
    {
      "Name": "SystemServerMemoryHighLimit",
      "Actions": [
        {
          "Name": "SetAttribute",
          "Params":
          {
            "Name": "MemHigh",
            "Value": "1080M"
          }
        }
      ]
    }
  ]
}

以下是 vendor/etc/pmgd/config.json 中 PMGD 配置的示例配置:

{
  "targets": [
    {
      "target_cmd": "system_server",
      "uid": 1000,
      "reclaim_wait_time_secs": 5,
      "mem_limit_profile": "SystemServerMemoryHighLimit",
      "anon_limit_in_mb": 300
    }
  ]
}