Android 17 以降では、プロセス メモリ ガーディアン デーモン(PMGD)がサポートされています。PMGD は、プロセスごとにメモリ使用量を積極的に管理することで、システムの健全性とユーザー エクスペリエンスを保護します。このデーモンは、特定のターゲット プロセスにメモリ上限を適切に適用し、分離されたメモリリークやスパイクがシステム全体のパフォーマンス低下を引き起こさないことを検証することで、デバイス全体の安定性を向上させます。
従来のグローバル低メモリ キラーはシステム全体に負荷がかかった場合にのみ動作しますが、PMGD はきめ細かいアプローチを採用しています。このデーモンは、ターゲット プロセスの Control Group v2 メモリの値をモニタリングすることで、これを実現します。ターゲット プロセスが構成されたメモリ上限を超えると、pmgd は、プロセスを終了する前に Statsd メモリ アトムを記録することで、上限違反を処理します。
仕組み
デーモンは inotify を使用してメモリ プレッシャー イベント(具体的には memory.events を使用した高メモリ アクティビティ)をリッスンします。モニタリング対象のプロセスがメモリ イベントをトリガーすると、pmgd は次のアクションを実行します。
- 匿名メモリのチェック: プロセスの匿名メモリを評価します。構成された
anon_limit_in_mbを超えると、pmgdはプロセスを直ちに強制終了します。 - 再利用待機期間: 匿名メモリが指定された匿名メモリ上限を下回っている場合、
pmgdはシステム再利用猶予期間(reclaim_wait_time_secs)を待ちます。 - 再利用後のメモリ評価: 猶予期間の経過後もターゲット プロセスの
memory.currentがmemory.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)。省略すると、pmgd は target_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
}
]
}