Cgroup-Abstraktionsschicht

Mit Sammlungen den Überblick behalten Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.

Android 10 und höher verwenden eine Kontrollgruppen-Abstraktionsschicht (cgroup) mit Aufgabenprofilen, die Entwickler verwenden können, um einen Satz (oder Sätze) von Einschränkungen zu beschreiben, die auf einen Thread oder einen Prozess anzuwenden sind. Das System folgt dann den vorgeschriebenen Aktionen der Aufgabenprofile, um eine oder mehrere geeignete Cgroups auszuwählen, durch die Einschränkungen angewendet werden, und Änderungen an dem zugrunde liegenden Cgroup-Funktionssatz können vorgenommen werden, ohne höhere Softwareschichten zu beeinträchtigen.

Über cgroups

Cgroups bieten einen Mechanismus zum Aggregieren und Partitionieren von Aufgabensätzen (die aus Prozessen, Threads und all ihren zukünftigen untergeordneten Elementen bestehen) in hierarchischen Gruppen mit spezialisiertem Verhalten. Android verwendet Cgroups, um Systemressourcen wie CPU- und Speichernutzung und -zuweisung zu steuern und zu berücksichtigen, mit Unterstützung für Linux-Kernel- Cgroups v1 und Cgroups v2 .

Android 9 und niedriger

In Android 9 und niedriger enthielt das Initialisierungsskript init.rc den Satz verfügbarer Kontrollgruppen, ihre Einhängepunkte und Versionen. Obwohl diese geändert werden konnten, erwartete das Android-Framework basierend auf dem Skript, dass ein bestimmter Satz von Cgroups an bestimmten Orten mit einer bestimmten Version und Untergruppenhierarchie vorhanden ist. Dies schränkte die Möglichkeit ein, die nächste Cgroup-Version auszuwählen oder die Cgroup-Hierarchie zu ändern, um neue Funktionen zu verwenden.

Android 10 und höher

Android 10 und höher verwenden cgroups mit Aufgabenprofilen:

  • Cgroup-Setup – Entwickler beschreiben das Cgroups-Setup in ihrer cgroups.json -Datei, um Sätze von Cgroups und ihre Mount-Orte und Attribute zu definieren. Alle Cgroups werden während der Early-Init-Phase des Initialisierungsprozesses gemountet.
  • Aufgabenprofile – diese bieten eine Abstraktion, die die erforderliche Funktionalität von den Details ihrer Implementierung entkoppelt. Das Android-Framework wendet die Aufgabenprofile wie in der Datei task_profiles.json beschrieben mithilfe der APIs SetTaskProfiles und SetProcessProfiles auf einen Prozess oder Thread an. (Diese APIs sind einzigartig für Android 11 und höher.)

Aus Gründen der Abwärtskompatibilität bieten die Legacy-Funktionen set_cpuset_policy , set_sched_policy und get_sched_policy die gleiche API und Funktionalität, aber ihre Implementierung wurde geändert, um Aufgabenprofile zu verwenden. Für neue Anwendungsfälle empfiehlt AOSP die Verwendung neuer Aufgabenprofil-APIs anstelle der Legacy-Funktion set_sched_policy .

Cgroups-Beschreibungsdatei

Cgroups werden in der Datei cgroups.json beschrieben, die sich unter <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ . Jeder Controller wird in einem Unterabschnitt beschrieben und muss mindestens Folgendes aufweisen:

  • Name, definiert durch das Controller -Feld.
  • Einhängepfad, definiert durch das Feld Pfad .
  • Modus , UID (Benutzer-ID) und GID (Gruppen-ID), die den Besitzer und die Zugriffsmodi für die Dateien unter diesem Pfad beschreiben (alle optional).
  • Optionales Attribut, auf true gesetzt, damit das System den Mount-Fehler ignoriert, der durch einen Cgroup-Controller verursacht wird, dessen Mount der Kernel nicht unterstützt.

Beispieldatei cgroups.json

Das folgende Beispiel zeigt Beschreibungen für cgroup v1 ( Cgroups ) und cgroup v2 ( Cgroups2 ) Controller mit ihren jeweiligen Pfaden.

{
  "Cgroups": [
    {
      "Controller": "cpu",
      "Path": "/dev/cpuctl",
      "Mode": "0755",
      "UID": "system",
      "GID": "system"
    },
    {
      "Controller": "memory",
      "Path": "/dev/memcg",
      "Mode": "0700",
      "Optional": true
    }
  ],
 "Cgroups2": {
   "Path": "/sys/fs/cgroup",
   "Mode": "0755",
   "UID": "system",
   "GID": "system",
   "Controllers": [
     {
       "Controller": "freezer",
       "Path": ".",
       "Mode": "0755",
       "UID": "system",
       "GID": "system"
     }
   ]
 }
}

Diese Beispieldatei enthält zwei Abschnitte, Cgroups (zur Beschreibung der cgroup v1-Controller) und Cgroups2 (zur Beschreibung der cgroup v2-Controller). Alle Controller in der cgroups v2-Hierarchie sind am selben Ort gemountet. Daher hat der Abschnitt Cgroups2 seine eigenen Attribute Path , Mode , UID und GID , um den Ort und die Attribute für den Stamm der Hierarchie zu beschreiben. Das Path -Attribut für Controller unter Cgroups2 ist relativ zu diesem Root-Pfad. In Android 12 und höher können Sie einen Cgroup-Controller definieren, der mit Pfad und Modus als "Optional" angegeben ist, indem Sie ihn auf true setzen.

Die cgroups.json -Datei wird als Teil des Init-Prozesses während der Early-Init-Phase analysiert, und die Cgroups werden an den angegebenen Speicherorten gemountet. Verwenden Sie die CgroupGetControllerPath API-Funktion, um später die Cgroup-Mounting-Speicherorte abzurufen.

Aufgabenprofildatei

Die Datei task_profiles.json befindet sich unter <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ . Verwenden Sie es, um einen bestimmten Satz von Aktionen zu beschreiben, die auf einen Prozess oder Thread angewendet werden sollen. Eine Reihe von Aktionen ist einem Profilnamen zugeordnet, der in SetTaskProfiles und SetProcessProfiles Aufrufen zum Aufrufen von Profilaktionen verwendet wird.

Beispieldatei task_profiles.json

{
  "Attributes": [
    {
      "Name": "MemSoftLimit",
      "Controller": "memory",
      "File": "memory.soft_limit_in_bytes"
    },
    {
      "Name": "MemSwappiness",
      "Controller": "memory",
      "File": "memory.swappiness"
    }
  ],
  "Profiles": [
    {
      "Name": "MaxPerformance",
      "Actions" : [
        {
          "Name" : "JoinCgroup",
          "Params" :
          {
            "Controller": "schedtune",
            "Path": "top-app"
          }
        }
      ]
    },
    {
      "Name": "TimerSlackHigh",
      "Actions" : [
        {
          "Name" : "SetTimerSlack",
          "Params" :
          {
            "Slack": "40000000"
          }
        }
      ]
    },
    {
      "Name": "LowMemoryUsage",
      "Actions" : [
        {
          "Name" : "SetAttribute",
          "Params" :
          {
            "Name" : "MemSoftLimit",
            "Value" : "16MB"
          }
        },
        {
          "Name" : "SetAttribute",
          "Params" :
          {
            "Name" : "MemSwappiness",
            "Value" : "150"

          }
        }
      ]
    }
  ]
  "AggregateProfiles": [
     {
       "Name": "SCHED_SP_DEFAULT",
       "Profiles": [ "TimerSlackHigh", "MaxPerformance" ]
     },
     {
       "Name": "SCHED_SP_BACKGROUND",
       "Profiles": [ "LowMemoryUsage" ]
     }
}

Weisen Sie bestimmten cgroup-Dateien Namen als Einträge in Ihrer Attributliste zu. Jeder Eintrag enthält Folgendes:

  • Namensfeld – gibt den Namen des Attributs an.
  • Controller -Feld – verweist anhand seines Namens auf einen cgroup-Controller aus der Datei cgroups.json .
  • Dateifeld - benennt eine bestimmte Datei unter diesem Controller.

Attribute sind Referenzen in Aufgabenprofildefinitionen. Verwenden Sie sie außerhalb von Aufgabenprofilen nur , wenn das Framework direkten Zugriff auf diese Dateien erfordert und der Zugriff nicht mithilfe von Aufgabenprofilen abstrahiert werden kann. Verwenden Sie in allen anderen Fällen Aufgabenprofile; sie sorgen für eine bessere Entkopplung zwischen dem erforderlichen Verhalten und seinen Implementierungsdetails.

Der Abschnitt Profile enthält Aufgabenprofildefinitionen mit Folgendem:

  • Namensfeld - definiert den Profilnamen.
  • Abschnitt „ Aktionen “ – listet eine Reihe von Aktionen auf, die ausgeführt werden, wenn das Profil angewendet wird. Jede Aktion hat Folgendes:

    • Namensfeld , das die Aktion angibt
    • Params- Abschnitt, der eine Reihe von Parametern für die Aktion angibt

Unterstützte Aktionen sind in der folgenden Tabelle aufgeführt.

Aktion Parameter Beschreibung
SetTimerSlack Slack Zeitverzögerung in ns
SetAttribute Name Ein Name, der auf ein Attribut aus dem Abschnitt " Attribute " verweist
Value Ein Wert, der in die Datei geschrieben werden soll, die durch das benannte Attribut dargestellt wird
WriteFile FilePath Pfad zur Datei
Value ein Wert, der in die Datei geschrieben werden soll
JoinCgroup Controller Ein Name des cgroup-Controllers aus cgroups.json
Path Ein Untergruppenpfad in der Hierarchie des Cgroup-Controllers

Android 12 und höher verfügen über einen AggregateProfiles -Abschnitt, der aggregierte Profile enthält, von denen jedes ein Alias ​​für einen Satz von einem oder mehreren Profilen ist. Aggregierte Profildefinitionen bestehen aus Folgendem:

  • Namensfeld – gibt den Namen des aggregierten Profils an.
  • Profile -Feld – listet die Namen der Profile auf, die im aggregierten Profil enthalten sind.

Wenn ein aggregiertes Profil angewendet wird, werden alle enthaltenden Profile ebenfalls automatisch angewendet. Aggregierte Profile können sowohl einzelne Profile als auch andere aggregierte Profile enthalten, solange es keine Rekursionen gibt (ein Profil, das sich selbst enthält).

task_profiles init Sprachbefehl

Ein task_profiles Befehl in der Android-Init-Sprache ist für Android 12 und höher verfügbar, um die Aktivierung von Aufgabenprofilen für einen bestimmten Prozess zu erleichtern. Es ersetzt den Befehl writepid (in Android 12 veraltet), der zum Migrieren eines Prozesses zwischen cgroups verwendet wurde. Der Befehl task_profiles bietet Flexibilität zum Ändern zugrunde liegender Implementierungen ohne Auswirkung auf obere Schichten. Im folgenden Beispiel führen diese beiden Befehle effektiv dieselbe Operation aus:

  • writepid /dev/cpuctl/top-app/tasks

    Veraltet in Android 12 – Wurde verwendet, um die PID der aktuellen Aufgabe in die Datei /dev/cpuctl/top-app/tasks zu schreiben.

  • task_profiles MaxPerformance

    Fügt den aktuellen Prozess in die Top-App-Gruppe unter dem "cpu"-Controller ( cpuctl ) ein, was dazu führt, dass die PID des Prozesses in dev/cpuctl/top-app/tasks wird.

Verwenden Sie immer den Befehl task_profiles , um Aufgaben in Cgroup-Hierarchien in Android 12 und höher zu migrieren. Es akzeptiert einen oder mehrere Parameter, die die Namen der Profile darstellen, die in der Datei task_profiles.json angegeben sind.

Aufgabenprofile auf API-Ebene

In Android 12 und höher können Sie Definitionen in den Standarddateien cgroups.json und task_profiles.json ändern oder überschreiben, indem Sie Ihre Änderung entweder auf der Android-API-Ebene basieren oder sie von der Anbieterpartition vornehmen.

Um die Definitionen basierend auf API-Ebene zu überschreiben, müssen die folgenden Dateien auf dem Gerät vorhanden sein:

  • pro/system/etc/task_profiles/cgroups_<API level>.json

    Verwenden Sie dies für Cgroups, die für eine API-Ebene spezifisch sind.

  • /system/etc/task_profiles/task_profiles_<API level>.json

    Verwenden Sie dies für Profile, die für eine API-Ebene spezifisch sind.

Um die Definitionen von der Herstellerpartition zu überschreiben, müssen die folgenden Dateien auf dem Gerät vorhanden sein:

  • /vendor/etc/cgroups.json
  • /vendor/etc/task_profiles.json

Wenn ein Attribut oder eine Profildefinition in diesen Dateien denselben Namen wie in der Standarddatei verwendet, überschreibt die Dateidefinition (auf API-Ebene oder Anbieterebene) die vorherige Definition. Beachten Sie auch, dass Definitionen auf Anbieterebene Definitionen auf API-Ebene außer Kraft setzen. Wenn die neue Definition einen neuen Namen hat, dann wird der Satz von Attributen oder Profilen mit der neuen Definition ergänzt.

Das Android-System lädt die cgroup und task_profile Dateien in dieser Reihenfolge:

  1. Standarddateien cgroups.json und task_profiles.json .
  2. API-Level-spezifische Dateien, falls vorhanden.
  3. Herstellerpartitionsdateien, falls vorhanden.

Änderungen an bestehender API

Android 10 und höher behält die Funktionen set_cpuset_policy , set_sched_policy und get_sched_policy ohne Änderungen an der API bei. Android 10 verschiebt diese Funktionen jedoch in libprocessgroup , das jetzt alle cgroup-bezogenen Funktionen enthält.

Obwohl der Header cutils/sched_policy.h noch vorhanden ist, stellen Sie sicher, dass neuer Code stattdessen einen neuen Header processgroup/sched_policy.h enthält, um zu vermeiden, dass vorhandener Code beschädigt wird.

Module, die eine dieser Funktionen verwenden, sollten ihrem Makefile eine Abhängigkeit von der libprocessgroup Bibliothek hinzufügen. Wenn ein Modul keine andere libcutils Funktionalität verwendet, löschen Sie die libcutils Bibliotheksabhängigkeit aus dem Makefile.

APIs für Aufgabenprofile

Die privaten APIs in processgroup/processgroup.h sind in der folgenden Tabelle definiert:

Art API und Definition
bool SetTaskProfiles(int tid, const std::vector & profiles) SetTaskProfiles(int tid, const std::vector & profiles)

Wendet die in den Profilen angegebenen Task- profiles auf den durch eine Thread-ID (tid) angegebenen Thread unter Verwendung des tid Parameters an.

bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles) SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles)

Wendet die in den profiles angegebenen Aufgabenprofile auf den Prozess an, der durch seine Benutzer- und Prozess-IDs unter Verwendung der Parameter uid und pid angegeben ist

bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)

Gibt zurück, ob ein durch cgroup_name angegebener cgroup-Controller existiert; Wenn true , wird die path auf das Stammverzeichnis dieser Kontrollgruppe gesetzt

bool CgroupGetAttributePath(const std::string& attr_name, std::string* path)

Gibt zurück, ob ein durch attr_name angegebenes attr_name existiert; Wenn true , wird die Pfadvariable auf den path der Datei festgelegt, die diesem Profilattribut zugeordnet ist.

bool CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)

Gibt zurück, ob ein durch attr_name angegebenes attr_name existiert; Wenn true , wird die path -Variable auf den Pfad der Datei gesetzt, die diesem Profilattribut zugeordnet ist, und auf den Thread, der durch seine Thread-ID unter Verwendung des tid -Parameters angegeben ist.

bool UsePerAppMemcg()

Gibt zurück, ob das System so konfiguriert ist, dass es Speicher-Cgroups pro Anwendung verwendet.