プロセスメモリ ガーディアン デーモン

Android 17 以降では、プロセス メモリ ガーディアン デーモン(PMGD)がサポートされています。PMGD は、プロセスごとにメモリ使用量を積極的に管理することで、システムの健全性とユーザー エクスペリエンスを保護します。このデーモンは、特定のターゲット プロセスにメモリ上限を適切に適用し、分離されたメモリリークやスパイクがシステム全体のパフォーマンス低下を引き起こさないことを検証することで、デバイス全体の安定性を向上させます。

従来のグローバル低メモリ キラーはシステム全体に負荷がかかった場合にのみ動作しますが、PMGD はきめ細かいアプローチを採用しています。このデーモンは、ターゲット プロセスの Control Group v2 メモリの値をモニタリングすることで、これを実現します。ターゲット プロセスが構成されたメモリ上限を超えると、pmgd は、プロセスを終了する前に Statsd メモリ アトムを記録することで、上限違反を処理します。

仕組み

デーモンは inotify を使用してメモリ プレッシャー イベント(具体的には memory.events を使用した高メモリ アクティビティ)をリッスンします。モニタリング対象のプロセスがメモリ イベントをトリガーすると、pmgd は次のアクションを実行します。

  1. 匿名メモリのチェック: プロセスの匿名メモリを評価します。構成された anon_limit_in_mb を超えると、pmgd はプロセスを直ちに強制終了します。
  2. 再利用待機期間: 匿名メモリが指定された匿名メモリ上限を下回っている場合、pmgd はシステム再利用猶予期間(reclaim_wait_time_secs)を待ちます。
  3. 再利用後のメモリ評価: 猶予期間の経過後もターゲット プロセスの memory.currentmemory.high 以上の場合、または 匿名メモリが anon_limit_in_mb を超える場合、pmgd はプロセスを直ちに強制終了します。

この処理は、プロセスが強制終了されるか、プロセスの再利用によってメモリ使用量が指定されたメモリ上限を下回るまで継続的に行われます。

システムの健全性機能

  • 再起動のレート制限: 起動ループやクラッシュの継続を防止するため、pmgd/data/misc/pmgd/history.json でプロセス終了を追跡します。デーモンは、デバイスの再起動ごとに 1 回の 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 によって構成されます。これは、追跡するプロセス、構成されたメモリ上限プロファイル(cgroup タスク プロファイルを使用)、匿名メモリのハード上限(メガバイト単位)を一覧表示します。

ベンダー構成フィールド

指定された JSON 構成は、次のフィールドで定義されたプロセスとその上限のリストです。

フィールド 必須 / 省略可 説明 デフォルト
target_cmd 文字列 モニタリングするターゲット プロセスのコマンド名(例: system_server)。 なし
uid Integer いいえ プロセスのユーザー ID(UID)。省略すると、pmgdtarget_cmd に一致するすべてのプロセスにルールをグローバルに適用します。 なし
reclaim_wait_time_secs Integer いいえ メモリ上限を再度評価する前に、システムがメモリを再利用するのを待機する猶予期間(秒単位)。 5
mem_limit_profile 文字列 `memory.high` を設定する cgroup タスク プロファイルの名前。これは、プロセス メモリの上限を設定するために使用されます。 なし
anon_limit_in_mb Integer 最終的な匿名メモリ上限(メガバイト単位)。匿名メモリの使用率がこの値を超えると、pmgd はプロセスを直ちに強制終了します。 なし
additional_task_profiles 文字列のリスト いいえ モニタリングの開始時に pmgd がプロセスに適用する追加のタスク プロファイルのリスト。 空のリスト

次に、vendor/etc/task_profiles.json の cgroup タスク プロファイルの構成例を示します。

{
  "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
    }
  ]
}