Android 10 i nowsze wersje korzystają z warstwy abstrakcji grupy kontrolnej (cgroup) z profilami zadań, których deweloperzy mogą używać do opisywania zestawu (lub zestawów) ograniczeń, które mają być stosowane do wątku lub procesu. System wykonuje następnie określone działania profili zadań, aby wybrać co najmniej jedną odpowiednią grupę kontrolną, za pomocą której stosowane są ograniczenia. Zmiany w podstawowym zestawie funkcji grupy kontrolnej można wprowadzać bez wpływu na wyższe warstwy oprogramowania.
Informacje o grupach kontrolnych
Cgroups to mechanizm agregowania i dzielenia zestawów zadań (składających się z procesów, wątków i wszystkich ich przyszłych elementów podrzędnych) na hierarchiczne grupy o specjalnym zachowaniu. Android używa grup kontrolnych do kontrolowania i rozliczania zasobów systemowych, takich jak wykorzystanie i przydzielanie procesora i pamięci, z obsługą grup kontrolnych v1 i v2 jądra Linux.
Android 9 i starsze
W Androidzie 9 i starszych wersjach skrypt inicjowania init.rc
zawierał zestaw dostępnych grup kontrolnych, ich punkty montowania i wersje. Chociaż można było je zmienić, platforma Android oczekiwała, że w określonych lokalizacjach będzie istniał konkretny zestaw grup kontrolnych o określonej wersji i hierarchii podgrup, zgodnie ze skryptem. Ograniczało to możliwość wyboru następnej wersji cgroup lub zmiany hierarchii cgroup w celu korzystania z nowych funkcji.
Android 10 lub nowszy
Android 10 i nowszy korzysta z grup kontrolnych z profilami zadań:
- Konfiguracja cgroup Deweloperzy opisują konfigurację cgroups w pliku
cgroups.json
, aby zdefiniować zestawy cgroups oraz ich lokalizacje montowania i atrybuty. Wszystkie grupy kontrolne są montowane na wczesnym etapie inicjowania. - Profile zadań Zapewniają one abstrakcję, która oddziela wymaganą funkcjonalność od szczegółów jej implementacji. Platforma Android stosuje profile zadań opisane w pliku
task_profiles.json
do procesu lub wątku za pomocą interfejsów APISetTaskProfiles
iSetProcessProfiles
. (Te interfejsy API są dostępne tylko na Androidzie 11 i nowszym).
Aby zapewnić zgodność wsteczną, starsze funkcje set_cpuset_policy
, set_sched_policy
i get_sched_policy
oferują ten sam interfejs API i te same funkcje, ale ich implementacja została zmodyfikowana w taki sposób, aby korzystać z profili zadań. W przypadku nowych przypadków użycia AOSP zaleca korzystanie z nowych interfejsów API profili zadań zamiast starszej funkcji set_sched_policy
.
Plik opisu grup kontrolnych
Grupy kontrolne są opisane w pliku cgroups.json
znajdującym się w katalogu <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Każdy kontroler jest opisany w podsekcji i musi zawierać co najmniej te elementy:
- Nazwa zdefiniowana w polu Administrator.
- Ścieżka podłączenia określona w polu Ścieżka.
- Mode, UID (identyfikator użytkownika) i GID (identyfikator grupy) opisujące właściciela i tryby dostępu do plików w tej ścieżce (wszystkie opcjonalne).
- Atrybut opcjonalny. Ustaw wartość true, aby system ignorował błąd montowania spowodowany przez kontroler cgroup, którego jądro nie obsługuje.
Przykładowy plik cgroups.json
Poniższy przykład zawiera opisy kontrolerów cgroup w wersji 1 (Cgroups
) i cgroup w wersji 2 (Cgroups2
) wraz z odpowiednimi ścieżkami.
{
"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"
}
]
}
}
Ten przykładowy plik zawiera 2 sekcje: Cgroups (opisującą kontrolery cgroup w wersji 1) i Cgroups2 (opisującą kontrolery cgroup w wersji 2). Wszystkie kontrolery w hierarchii cgroups w wersji 2 są montowane w tej samej lokalizacji.
Dlatego sekcja Cgroups2 ma własne atrybuty Path, Mode, UID i GID, które opisują lokalizację i atrybuty korzenia hierarchii. Atrybut Ścieżka dla Kontrolerów w sekcji Cgroups2 jest podawany w odniesieniu do tej ścieżki głównej. W Androidzie 12 i nowszych możesz zdefiniować kontroler cgroup określony za pomocą ścieżki i trybu jako "Optional"
, ustawiając go na true
.
Plik cgroups.json
jest analizowany w ramach procesu inicjowania, na etapie wczesnego inicjowania, a grupy kontrolne są montowane w określonych lokalizacjach. Aby później uzyskać lokalizacje montowania cgroup, użyj funkcji interfejsu API CgroupGetControllerPath
.
Plik profili zadań
Plik task_profiles.json
znajduje się w lokalizacji <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Używaj go do opisywania określonego zestawu działań, które mają być zastosowane w procesie lub wątku. Z nazwą profilu powiązany jest zestaw działań, który jest używany w wywołaniach SetTaskProfiles
i SetProcessProfiles
do wywoływania działań profilu.
Przykładowy plik 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" ]
}
}
Przypisz nazwy do konkretnych plików cgroup jako wpisy na liście Atrybuty. Każdy wpis zawiera te informacje:
- Pole Nazwa określa nazwę atrybutu.
- Pole Controller odwołuje się do kontrolera cgroup z pliku
cgroups.json
według jego nazwy. - Pole File (Plik) zawiera nazwę konkretnego pliku w ramach tego administratora.
Atrybuty to odwołania w definicjach profili zadań. Poza profilami zadań używaj ich tylko wtedy, gdy platforma wymaga bezpośredniego dostępu do tych plików, a dostęp nie może być abstrakcyjny przy użyciu profili zadań. We wszystkich pozostałych przypadkach używaj profili zadań. Zapewniają one lepsze rozdzielenie wymaganego działania od szczegółów jego implementacji.
Sekcja Profile (Profile) zawiera definicje profili zadań z tymi informacjami:
- Pole Nazwa określa nazwę profilu.
W sekcji Działania znajduje się lista działań wykonywanych po zastosowaniu profilu. Każda czynność ma te elementy:
- Pole Nazwa określa działanie.
- Sekcja Params określa zestaw parametrów działania.
Obsługiwane działania znajdziesz w tabeli:
Działanie | Parametr | Opis |
---|---|---|
SetTimerSlack |
Slack |
Opóźnienie timera w nanosekundach |
SetAttribute |
Name |
Nazwa odwołująca się do atrybutu z sekcji Atrybuty. |
Value |
Wartość do zapisania w pliku reprezentowanym przez atrybut o podanej nazwie. | |
WriteFile | FilePath | ścieżka do pliku, |
Value | wartość do zapisania w pliku; | |
JoinCgroup |
Controller |
Nazwa kontrolera cgroup z cgroups.json |
Path |
Ścieżka podgrupy w hierarchii kontrolera cgroup. |
Android 12 i nowsze wersje zawierają sekcję AggregateProfiles, która zawiera profile zbiorcze. Każdy z nich jest aliasem dla zestawu co najmniej 1 profilu. Definicje profilu zbiorczego składają się z tych elementów:
- Pole Nazwa określa nazwę profilu zbiorczego.
- W polu Profile (Profile) wyświetlają się nazwy profili uwzględnionych w profilu zbiorczym.
Gdy zastosujesz profil zbiorczy, wszystkie profile, które zawiera, zostaną również zastosowane automatycznie. Profile zbiorcze mogą zawierać zarówno profile indywidualne, jak i inne profile zbiorcze, o ile nie ma rekursji (profilu, który zawiera sam siebie).
task_profiles init language command
W języku inicjowania Androida dostępna jest komenda task_profiles
, która umożliwia aktywowanie profilu zadania dla określonego procesu na urządzeniach z Androidem 12 lub nowszym. Zastępuje polecenie writepid
(wycofane w Androidzie 12), które służyło do przenoszenia procesu między grupami kontrolnymi. Polecenie task_profiles
zapewnia elastyczność w zakresie zmiany implementacji bazowych bez wpływu na wyższe warstwy. W przykładzie poniżej oba polecenia wykonują to samo działanie:
writepid /dev/cpuctl/top-app/tasks
Wycofana w Androidzie 12. Służyła do zapisywania identyfikatora PID bieżącego zadania w pliku
/dev/cpuctl/top-app/tasks
.task_profiles MaxPerformance
Dołącza bieżący proces do grupy najważniejszych aplikacji w kontrolerze „cpu” (
cpuctl
), co powoduje zapisanie identyfikatora PID procesu wdev/cpuctl/top-app/tasks
.
Zawsze używaj polecenia task_profiles
, aby migrować zadania w hierarchiach grup kontrolnych w Androidzie 12 i nowszych. Akceptuje co najmniej 1 parametr, który reprezentuje nazwy profili podane w pliku task_profiles.json
.
Profile zadań na poziomie interfejsu API
Na Androidzie 12 i nowszym możesz modyfikować lub zastępować definicje w domyślnych plikach cgroups.json
i task_profiles.json
, opierając zmiany na poziomie interfejsu Android API lub wprowadzając je z partycji dostawcy.
Aby zastąpić definicje na podstawie poziomu interfejsu API, na urządzeniu muszą być obecne te pliki:
/system/etc/task_profiles/cgroups_<API level>.json
Użyj tej opcji w przypadku grup kontrolnych specyficznych dla poziomu interfejsu API.
/system/etc/task_profiles/task_profiles_<API level>.json
Użyj tego w przypadku profili specyficznych dla poziomu interfejsu API.
Aby zastąpić definicje z partycji dostawcy, na urządzeniu muszą być obecne te pliki:
/vendor/etc/cgroups.json
/vendor/etc/task_profiles.json
Jeśli atrybut lub definicja profilu w tych plikach ma taką samą nazwę jak w pliku domyślnym, definicja pliku (na poziomie interfejsu API lub dostawcy) zastępuje poprzednią definicję. Pamiętaj też, że definicje na poziomie dostawcy zastępują definicje na poziomie interfejsu API. Jeśli nowa definicja ma nową nazwę, zestaw atrybutów lub profili zostanie uzupełniony o nową definicję.
System Android wczytuje pliki cgroup
i task_profile
w tej kolejności:
- Domyślne pliki
cgroups.json
itask_profiles.json
. - pliki specyficzne dla poziomu interfejsu API (jeśli występują);
- Pliki partycji dostawcy, jeśli są dostępne.
Zmiany w istniejącym interfejsie API
Android 10 i nowsze wersje zachowują funkcje set_cpuset_policy
, set_sched_policy
i get_sched_policy
bez zmian w interfejsie API.
W Androidzie 10 te funkcje zostały jednak przeniesione do libprocessgroup
, które zawiera teraz wszystkie funkcje związane z cgroup.
Chociaż nagłówek cutils/sched_policy.h
nadal istnieje, aby uniknąć uszkodzenia istniejącego kodu, upewnij się, że nowy kod zawiera nowy nagłówek processgroup/sched_policy.h
.
Moduły, które używają którejkolwiek z tych funkcji, powinny dodać zależność od biblioteki libprocessgroup
do pliku makefile. Jeśli moduł nie korzysta z żadnych innych funkcji libcutils
, usuń zależność biblioteki libcutils
z pliku makefile.
Interfejsy API profili zadań
Prywatne interfejsy API w processgroup/processgroup.h
są zdefiniowane w tej tabeli:
Typ | Interfejs API i definicja |
---|---|
bool |
SetTaskProfiles(int tid, const std::vector
Stosuje profile zadań określone w parametrze profiles do wątku określonego przez identyfikator wątku (tid) za pomocą parametru tid . |
bool |
SetProcessProfiles(uid_t uid, pid_t pid, const std::vector
Stosuje profile zadań określone w parametrze profiles do procesu określonego przez identyfikatory użytkownika i procesu za pomocą parametrów uid i pid . |
bool |
CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
Zwraca informację, czy istnieje kontroler cgroup określony przez cgroup_name ; jeśli true , ustawia zmienną path na katalog główny tej grupy cgroup. |
bool |
CgroupGetAttributePath(const std::string& attr_name, std::string* path)
Zwraca informację, czy atrybut profilu określony przez attr_name istnieje. Jeśli tak, ustawia zmienną path na ścieżkę pliku powiązanego z tym atrybutem profilu.true |
bool |
CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)
Zwraca informację, czy istnieje atrybut profilu określony przez attr_name . Jeśli true , ustawia zmienną path na ścieżkę pliku powiązanego z tym atrybutem profilu oraz na wątek określony przez jego identyfikator wątku za pomocą parametru tid . |
bool |
UsePerAppMemcg()
Zwraca informację, czy system jest skonfigurowany do używania grup kontrolnych pamięci dla poszczególnych aplikacji. |