Android 10 und höher verwenden eine Abstraktionsschicht für eine Kontrollgruppe (Control Group, cgroup) mit Aufgabenprofilen, mit denen Entwickler eine Reihe von Einschränkungen für einen Thread oder Prozess beschreiben können. Das System führt dann die vorgeschriebenen Aktionen der Aufgabenprofile aus, um eine oder mehrere geeignete Cgroups auszuwählen, über die Einschränkungen angewendet werden. Änderungen an der zugrunde liegenden Cgroup-Funktionsgruppe können vorgenommen werden, ohne dass höhere Softwareschichten beeinträchtigt werden.
Cgroups
Cgroups bieten einen Mechanismus zum Aggregieren und Partitionieren von Aufgaben (bestehend aus Prozessen, Threads und allen zukünftigen untergeordneten Elementen) in hierarchische Gruppen mit speziellem Verhalten. Android verwendet cgroups, um Systemressourcen wie CPU- und Arbeitsspeichernutzung und -zuweisung zu steuern und zu berücksichtigen. Dabei wird cgroups v1 und cgroups v2 des Linux-Kernels unterstützt.
Android 9 und niedriger
In Android 9 und niedriger enthielt das init.rc
-Initialisierungsskript die verfügbaren cgroups, ihre Bereitstellungspunkte und Versionen. Diese können zwar geändert werden, das Android-Framework erwartet jedoch, dass an bestimmten Stellen eine bestimmte Gruppe von Cgroups mit einer bestimmten Version und einer bestimmten Hierarchie von Untergruppen vorhanden ist, basierend auf dem Script. Dadurch war es nicht möglich, die nächste zu verwendende cgroup-Version auszuwählen oder die cgroup-Hierarchie so zu ändern, dass neue Funktionen verwendet werden.
Android 10 und höher
Unter Android 10 und höher werden cgroups mit Aufgabenprofilen verwendet:
- Cgroup-Einrichtung Entwickler beschreiben die Cgroups-Einrichtung in ihrer
cgroups.json
-Datei, um Cgroups-Gruppen sowie ihre Bereitstellungsorte und Attribute zu definieren. Alle cgroups werden während der frühen Initialisierungsphase des Initialisierungsprozesses bereitgestellt. - Aufgabenprofile Sie bieten eine Abstraktion, die die erforderliche Funktionalität von den Details ihrer Implementierung trennt. Das Android-Framework wendet die in der
task_profiles.json
-Datei beschriebenen Aufgabenprofile mithilfe derSetTaskProfiles
- undSetProcessProfiles
-APIs auf einen Prozess oder Thread an. (Diese APIs sind nur für Android 11 und höher verfügbar.)
Aus Gründen der Abwärtskompatibilität bieten die bisherigen Funktionen set_cpuset_policy
, set_sched_policy
und get_sched_policy
dieselbe API und Funktionalität. Ihre Implementierung wurde jedoch so geändert, dass Aufgabenprofile verwendet werden. Für neue Anwendungsfälle empfiehlt AOSP die Verwendung neuer APIs für Aufgabenprofile anstelle der alten set_sched_policy
-Funktion.
Cgroups-Beschreibungsdatei
Cgroups werden in der Datei cgroups.json
unter <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
beschrieben.
Jeder Controller wird in einem Unterabschnitt beschrieben und muss mindestens die folgenden Anforderungen erfüllen:
- Name, definiert durch das Feld Controller.
- Bereitstellungspfad, definiert durch das Feld Pfad.
- Modus, UID (Nutzer-ID) und GID (Gruppen-ID), die den Inhaber und die Zugriffsmodi für die Dateien unter diesem Pfad beschreiben (alle optional).
- Optionales Attribut. Wenn es auf true gesetzt ist, ignoriert das System den Bereitstellungsfehler, der durch einen Cgroup-Controller verursacht wird, dessen Bereitstellung vom Kernel nicht unterstützt wird.
Beispiel für eine cgroups.json-Datei
Im folgenden Beispiel sind Beschreibungen für cgroup v1- (Cgroups
) und cgroup v2-Controller (Cgroups2
) mit ihren jeweiligen Pfaden zu sehen.
{
"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 (Beschreibung der cgroup v1-Controller) und Cgroups2 (Beschreibung der cgroup v2-Controller). Alle Controller in der cgroups v2-Hierarchie werden am selben Speicherort bereitgestellt.
Daher hat der Abschnitt Cgroups2 eigene Attribute Path, Mode, UID und GID, um den Speicherort und die Attribute für die Wurzel der Hierarchie zu beschreiben. Das Attribut Path für Controllers unter Cgroups2 ist relativ zu diesem Stammpfad. Unter 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
festlegen.
Die Datei cgroups.json
wird im Rahmen des Init-Prozesses in der frühen Init-Phase geparst und die cgroups werden an den angegebenen Speicherorten bereitgestellt. Wenn Sie die Bereitstellungsorte der cgroup später abrufen möchten, verwenden Sie die API-Funktion CgroupGetControllerPath
.
Datei „Aufgabenprofile“
Die Datei task_profiles.json
befindet sich unter <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Mit diesem Befehl können Sie eine bestimmte Reihe von Aktionen beschreiben, die auf einen Prozess oder einen Thread angewendet werden sollen. Einem Profilnamen ist eine Reihe von Aktionen zugewiesen, die in SetTaskProfiles
- und SetProcessProfiles
-Aufrufen verwendet werden, um Profilaktionen aufzurufen.
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 der Liste Attribute zu. Jeder Eintrag enthält Folgendes:
- Im Feld Name wird der Name des Attributs angegeben.
- Das Feld Controller verweist auf einen Cgroup-Controller aus der Datei
cgroups.json
, und zwar anhand seines Namens. - Im Feld Datei wird eine bestimmte Datei unter diesem Controller angegeben.
Attribute sind Verweise in den Definitionen von Aufgabenprofilen. Verwenden Sie sie außerhalb von Aufgabenprofilen nur, wenn das Framework direkten Zugriff auf diese Dateien benötigt und der Zugriff nicht mithilfe von Aufgabenprofilen abstrahiert werden kann. In allen anderen Fällen sollten Sie Aufgabenprofile verwenden. Sie ermöglichen eine bessere Entkopplung zwischen dem erforderlichen Verhalten und den Implementierungsdetails.
Der Bereich Profile enthält Definitionen für Aufgabenprofile mit folgenden Angaben:
- Im Feld Name wird der Profilname definiert.
Im Abschnitt Aktionen sind die Aktionen aufgeführt, die ausgeführt werden, wenn das Profil angewendet wird. Jede Aktion hat Folgendes:
- Im Feld Name wird die Aktion angegeben.
- Im Abschnitt Params werden eine Reihe von Parametern für die Aktion angegeben.
Die unterstützten Aktionen sind in der Tabelle aufgeführt:
Aktion | Parameter | Beschreibung |
---|---|---|
SetTimerSlack |
Slack |
Timer-Toleranz 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 | 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 enthalten den Abschnitt AggregateProfiles mit zusammengefassten Profilen. Jeder Alias steht für ein oder mehrere Profile. Definitionen für zusammengefasste Profile bestehen aus den folgenden Elementen:
- Im Feld Name wird der Name des zusammengefassten Profils angegeben.
- Im Feld Profile sind die Namen der Profile aufgeführt, die im zusammengefassten Profil enthalten sind.
Wenn ein zusammengefasstes Profil angewendet wird, werden automatisch auch alle enthaltenen Profile angewendet. Aggregierungsprofile können sowohl einzelne Profile als auch andere Aggregierungsprofile enthalten, sofern keine Rekursionen (Profile, die sich selbst enthalten) vorhanden sind.
Befehl „task_profiles init language“
Unter Android 12 und höher ist der Befehl task_profiles
in der Android Init Language verfügbar, um die Aktivierung des Aufgabenprofils für einen bestimmten Prozess zu vereinfachen. Er ersetzt den Befehl writepid
(in Android 12 eingestellt), mit dem ein Prozess zwischen Cgroups migriert wurde. Der Befehl task_profiles
bietet Flexibilität bei der Änderung der zugrunde liegenden Implementierungen, ohne dass sich dies auf die höheren Schichten auswirkt. Im folgenden Beispiel führen diese beiden Befehle dieselbe Aktion aus:
writepid /dev/cpuctl/top-app/tasks
In Android 12 nicht mehr unterstützt. Damit wurde die PID der aktuellen Aufgabe in die Datei
/dev/cpuctl/top-app/tasks
geschrieben.task_profiles MaxPerformance
Der aktuelle Prozess wird der Top-App-Gruppe unter dem „cpu“-Controller (
cpuctl
) zugeordnet. Dadurch wird die PID des Prozesses indev/cpuctl/top-app/tasks
geschrieben.
Verwenden Sie unter Android 12 und höher immer den Befehl task_profiles
, um Aufgaben in Cgroup-Hierarchien zu migrieren. Es werden ein oder mehrere Parameter akzeptiert, die die Namen der in der task_profiles.json
-Datei angegebenen Profile darstellen.
Aufgabenprofile auf API-Ebene
Unter Android 12 und höher können Sie Definitionen in den Standarddateien cgroups.json
und task_profiles.json
ändern oder überschreiben. Sie können die Änderung entweder auf der Android API-Ebene vornehmen oder über die Anbieterpartition.
Wenn Sie die Definitionen auf API-Ebene überschreiben möchten, müssen die folgenden Dateien auf dem Gerät vorhanden sein:
/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 diese Option für Profile, die für eine API-Ebene spezifisch sind.
Wenn Sie die Definitionen aus der Anbieterpartition überschreiben möchten, 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 hat, wird die vorherige Definition durch die Dateidefinition (auf API-Ebene oder Anbieterebene) überschrieben. Beachten Sie außerdem, dass Definitionen auf Anbieterebene Definitionen auf API-Ebene überschreiben. Wenn die neue Definition einen neuen Namen hat, wird die Gruppe der Attribute oder Profile mit der neuen Definition ergänzt.
Das Android-System lädt die Dateien cgroup
und task_profile
in dieser Reihenfolge:
- Standarddateien
cgroups.json
undtask_profiles.json
. - Dateien auf API-Ebene, falls vorhanden.
- Partitionsdateien des Anbieters, falls vorhanden.
Änderungen an der vorhandenen API
Unter Android 10 und höher bleiben die Funktionen set_cpuset_policy
, set_sched_policy
und get_sched_policy
ohne Änderungen an der API erhalten.
In Android 10 werden diese Funktionen jedoch in libprocessgroup
verschoben, das jetzt alle cgroup-bezogenen Funktionen enthält.
Auch wenn der cutils/sched_policy.h
-Header weiterhin vorhanden ist, muss der neue Code einen neuen processgroup/sched_policy.h
-Header enthalten, damit der vorhandene Code nicht beschädigt wird.
Module, in denen eine dieser Funktionen verwendet wird, sollten in ihrem Makefile eine Abhängigkeit von der libprocessgroup
-Bibliothek angeben. Wenn ein Modul keine anderen libcutils
-Funktionen verwendet, entfernen Sie die libcutils
-Bibliotheksabhängigkeit aus dem Makefile.
APIs für Aufgabenprofile
Die privaten APIs in processgroup/processgroup.h
sind in der Tabelle definiert:
Eingeben | API und Definition |
---|---|
bool |
SetTaskProfiles(int tid, const std::vector
Wendet die in profiles angegebenen Aufgabenprofile mithilfe des Parameters tid auf den Thread an, der durch eine Thread-ID (tid) angegeben ist. |
bool |
SetProcessProfiles(uid_t uid, pid_t pid, const std::vector
Wendet die in profiles angegebenen Aufgabenprofile mithilfe der Parameter uid und pid auf den Prozess an, der durch seine Nutzer- und Prozess-IDs angegeben ist. |
bool |
CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
Gibt an, ob ein mit cgroup_name angegebener cgroup-Controller vorhanden ist. Wenn true , wird die Variable path auf den Stamm dieser cgroup gesetzt. |
bool |
CgroupGetAttributePath(const std::string& attr_name, std::string* path)
Gibt an, ob ein mit attr_name angegebenes Profilattribut vorhanden ist. Wenn true , wird die Variable path auf den Pfad der Datei festgelegt, die mit diesem Profilattribut verknüpft ist. |
bool |
CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)
Gibt an, ob ein mit attr_name angegebenes Profilattribut vorhanden ist. Wenn true , wird die Variable path auf den Pfad der Datei festgelegt, die mit diesem Profilattribut verknüpft ist, und auf den Thread, der über die Thread-ID mit dem Parameter tid angegeben ist. |
bool |
UsePerAppMemcg()
Gibt zurück, ob das System für die Verwendung von speicherspezifischen Cgroups pro Anwendung konfiguriert ist. |