Daemon de protection de la mémoire des processus

Android 17 et versions ultérieures sont compatibles avec le daemon PMGD (Process Memory Guardian Daemon), qui protège l'état du système et l'expérience utilisateur en gérant de manière proactive l'utilisation de la mémoire par processus. Le daemon améliore la stabilité globale de l'appareil en appliquant des limites de mémoire à des processus cibles spécifiques, et en vérifiant que les fuites ou les pics de mémoire isolés n'entraînent pas de dégradation des performances à l'échelle du système.

Alors que les robots tueurs de mémoire conventionnels n'agissent que lorsque l'ensemble du système est sous pression, PMGD adopte une approche plus précise. Pour ce faire, le daemon atteint ce en surveillant les valeurs de mémoire du groupe de contrôle v2 pour ses processus cibles. Lorsqu'un processus ciblé dépasse ses limites de mémoire configurées, pmgd gère les violations de limite en enregistrant les atomes de mémoire Statsd avant de mettre fin au processus.

Fonctionnement

Le daemon utilise inotify pour écouter les événements de pression de la mémoire (en particulier l'activité de mémoire élevée à l'aide de memory.events). Lorsqu'un processus surveillé déclenche un événement de mémoire, pmgd effectue les actions suivantes :

  1. Vérification de la mémoire anonyme : évalue la mémoire anonyme du processus. Si elle dépasse la valeur anon_limit_in_mb configurée, pmgd arrête immédiatement le processus.
  2. Période d'attente de récupération : si la mémoire anonyme est inférieure à la limite de mémoire anonyme spécifiée, pmgd attend une période de grâce de récupération du système (reclaim_wait_time_secs).
  3. Évaluation de la mémoire après récupération : si la valeur memory.current du processus cible reste supérieure ou égale à memory.high après la période de grâce, ou si la mémoire anonyme dépasse anon_limit_in_mb, pmgd arrête immédiatement le processus.

Cette opération est effectuée en continu jusqu'à ce que le processus soit arrêté ou que la récupération sur le processus réduise son utilisation de la mémoire en dessous des limites de mémoire spécifiées.

Fonctionnalités de santé du système

  • Limitation du taux de redémarrage : pour éviter les boucles de démarrage ou les plantages persistants, pmgd suit les arrêts de processus dans /data/misc/pmgd/history.json. Le daemon limite les processus à un seul arrêt initié par pmgd par redémarrage de l'appareil.

Configuration SELinux

La capacité de PMGD à surveiller les processus est limitée par la règle SELinux. Si vous configurez PMGD pour surveiller un processus dont le domaine n'est pas autorisé par la règle, tel qu'un processus système spécifique au fournisseur, PMGD ne peut pas le surveiller et vous pouvez voir des refus SELinux dans logcat.

Pour autoriser PMGD à surveiller les processus dans des domaines supplémentaires, vous devez étendre les autorisations de PMGD en mettant à jour la règle SELinux spécifique à votre appareil pour PMGD.

Voici un exemple de fichier device/<vendor>/<device>/sepolicy/pmgd.te qui ajoute l'accès à un nouveau domaine :

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

Pour en savoir plus sur l'écriture d'une règle spécifique à un appareil, consultez Implémenter SELinux.

Configuration définie par le fournisseur

La configuration de PMGD est gérée par le fournisseur et configurée par un fichier JSON obligatoire /vendor/etc/pmgd/config.json. Ce fichier répertorie les processus à suivre, leur profil de limite de mémoire configuré (à l'aide de profils de tâches cgroup), et la limite de mémoire anonyme stricte en mégaoctets.

Champs de configuration du fournisseur

La configuration JSON fournie est une liste de processus et de leurs limites, définies par les champs suivants :

Champ Type Obligatoire Description Par défaut
target_cmd Chaîne Oui Nom de la commande du processus cible à surveiller, par exemple system_server. N/A
uid Nombre entier Non ID utilisateur (UID) du processus. En cas d'omission, pmgd applique la règle globalement à tout processus correspondant à target_cmd. N/A
reclaim_wait_time_secs Nombre entier Non Période de grâce en secondes pendant laquelle le système récupère de la mémoire avant de réévaluer la limite de mémoire. 5
mem_limit_profile Chaîne Oui Nom du profil de tâche cgroup qui définit `memory.high`. Il permet de définir la limite de mémoire du processus. N/A
anon_limit_in_mb Nombre entier Oui Limite de mémoire anonyme ultime en mégaoctets. Si l'utilisation de la mémoire anonyme dépasse cette valeur, pmgd arrête rapidement le processus. N/A
additional_task_profiles Liste de chaînes Non Liste de tous les profils de tâches supplémentaires que pmgd applique au processus au début de la surveillance. Liste vide

Voici un exemple de configuration du profil de tâche cgroup dans vendor/etc/task_profiles.json :

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

Voici un exemple de configuration de PMGD dans vendor/etc/pmgd/config.json :

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