Android 10 i nowsze wersje używają warstwy abstrakcji grupy sterowania (cgroup) z profilami zadań, których deweloperzy mogą używać do opisywania zestawów ograniczeń do zastosowania w wątku lub procesie. Następnie system wykonuje określone działania w ramach profili zadań, aby wybrać co najmniej jedną odpowiednią grupę cgroup, w której są stosowane ograniczenia, oraz wprowadzić zmiany w podstawowym zbiorze funkcji cgroup bez wpływu na wyższe warstwy oprogramowania.
Grupy
Grupy Cgroups stanowią mechanizm służący do agregowania i dzielenia zbiorów zadań (które składają się z procesów, wątków i wszystkich ich przyszłych elementów podrzędnych) na grupy hierarchiczne o specjalnym zachowaniu. Android używa cgroups do kontrolowania zasobów systemu, takich jak wykorzystanie i przydzielanie procesora i pamięci, z obsługą cgroups w jądrze Linux v1 i cgroups v2.
Android 9 i starsze
W Androidzie 9 i starszych wersjach skrypt inicjowania init.rc
zawierał zestaw dostępnych grup grup, ich punkty podłączania i wersje. Chociaż można je zmienić, platforma Android oczekuje, że w określonych miejscach w ramach skryptu będzie istniał określony zestaw grup, z określoną wersją i hierarchią podgrup. Ograniczało to możliwość wybrania kolejnej wersji cgroup do użycia lub zmiany hierarchii cgroup w celu użycia nowych funkcji.
Android 10 lub nowszy
Android 10 i nowsze korzystają z grup użytkowników z profilami zadań:
- Konfigurowanie grupy C. Deweloperzy opisują konfigurację grup cgroup w pliku
cgroups.json
, aby zdefiniować zestawy grup cgroup oraz ich lokalizacje i atrybuty. Wszystkie grupy są montowane na wczesnym etapie procesu inicjalizacji. - Profile zadań. Zapewniają one abstrakcję, która odłącza wymaganą funkcjonalność od szczegółów jej implementacji. Platforma Androida stosuje profile zadań zgodnie z opisem 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 nowszych).
Aby zapewnić zgodność wsteczną, funkcje poprzedniej wersji set_cpuset_policy
, set_sched_policy
i get_sched_policy
udostępniają ten sam interfejs API i te same funkcje, ale ich implementacja została zmodyfikowana, aby używać profili zadań. W przypadku nowych zastosowań AOSP zaleca używanie nowych interfejsów API profili zadań zamiast starszej funkcji set_sched_policy
.
Plik z opisem grup
Grupy C zostały opisane w pliku cgroups.json
znajdującym się w folderze <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Każdy kontroler jest opisany w podrozdziale i musi mieć co najmniej te elementy:
- Nazwa określona w polu Administrator.
- Ścieżka podłączenia określona przez pole Ścieżka.
- Tryb, 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).
- Opcjonalny atrybut. Ustaw go na true, aby system ignorował błąd zamontowania spowodowany przez kontroler cgroup, którego jądro nie obsługuje.
Przykładowy plik cgroups.json
Przykład poniżej 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ąca kontrolery cgroup v1) i Cgroups2 (opisująca kontrolery cgroup v2). Wszystkie kontrolery w hierarchii grup konfiguracji v2 są zamontowane w tej samej lokalizacji.
Dlatego sekcja Cgroups2 ma własne atrybuty Ścieżka, Tryb, UID i GID służące do opisania lokalizacji i atrybutów głównej hierarchii. Atrybut Ścieżka w przypadku elementu Controllers w sekcji Cgroups2 jest podany w odniesieniu do tej ścieżki głównej. W Androidzie 12 i nowszych możesz zdefiniować kontroler cgroup, który jest określony za pomocą ścieżki i trybu jako "Optional"
, ustawiając go na true
.
Plik cgroups.json
jest analizowany w ramach procesu inicjalizacji na wczesnym etapie inicjalizacji, a grupy C są montowane w określonych lokalizacjach. Aby później uzyskać lokalizacje montażu cgroup, użyj funkcji interfejsu API CgroupGetControllerPath
.
Plik profili zadań
Plik task_profiles.json
znajduje się w folderze <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Używaj go do opisywania konkretnego zestawu działań, które mają być wykonywane w ramach procesu 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:
- Pole Nazwa określa nazwę atrybutu.
- Pole Controller (sterownik) odwołuje się do sterownika cgroup z pliku
cgroups.json
według jego nazwy. - Pole Plik zawiera nazwę konkretnego pliku w ramach tego kontrolera.
Atrybuty to odniesienia w definicjach profili zadań. Poza profilami zadań używaj ich tylko wtedy, gdy platforma wymaga bezpośredniego dostępu do tych plików i że dostępu nie można pobierać za pomocą profili zadań. We wszystkich innych przypadkach korzystaj z profili zadań – ułatwiają one oddzielenie wymaganego działania od szczegółów jego implementacji.
Sekcja Profile zawiera definicje profili zadań z tymi elementami:
- Pole Nazwa określa nazwę profilu.
Sekcja Działania zawiera zestaw działań wykonywanych po zastosowaniu profilu. Każde działanie obejmuje:
- Pole Nazwa określa działanie.
- Sekcja Parametr określa zestaw parametrów działania.
Obsługiwane działania znajdziesz w tabeli:
Działanie | Parametr | Opis |
---|---|---|
SetTimerSlack |
Slack |
Czas opóźnienia w ns |
SetAttribute |
Name |
nazwa odwołująca się do atrybutu z sekcji Atrybuty. |
Value |
Wartość do zapisania w pliku reprezentowanym przez atrybuty o 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 grupy |
Android 12 i nowsze wersje zawierają sekcję AggregateProfiles, która zawiera profile zbiorcze. Każdy z nich jest aliasem zestawu co najmniej 1 profilu. Definicje profili zbiorczych obejmują:
- Pole Nazwa określa nazwę profilu zbiorczego.
- W polu Profile (Profile) podana jest lista nazw profili uwzględnionych w profilu zbiorczym.
Gdy zastosujesz profil zbiorczy, wszystkie profile go zawierające zostaną automatycznie zastosowane. Profile zbiorcze mogą zawierać zarówno profile indywidualne, jak i inne profile zbiorcze, o ile nie ma rekurencji (profilu, który zawiera sam siebie).
Polecenie init language w task_profiles
W Androidzie 12 i nowszych dostępna jest komenda task_profiles
w języku inicjalizacji Androida, która ułatwia aktywację profilu zadania w przypadku konkretnego procesu. Zastępuje on polecenie writepid
(wycofane w Androidzie 12), które służyło do przenoszenia procesu między grupami użytkowników. Polecenie task_profiles
zapewnia elastyczność w zakresie zmiany implementacji podrzędnych bez wpływu na warstwy wyższe. W przykładzie poniżej te 2 polecenia wykonują tę samą operację:
writepid /dev/cpuctl/top-app/tasks
Ta funkcja została wycofana w Androidzie 12. Służyła do zapisywania PID bieżącego zadania w pliku
/dev/cpuctl/top-app/tasks
.task_profiles MaxPerformance
Dołącza bieżący proces do grupy najlepszych aplikacji w ramach kontrolera „cpu” (
cpuctl
), co powoduje zapisanie identyfikatora PID procesu w miejscudev/cpuctl/top-app/tasks
.
W Androidzie 12 i nowszych wersjach zawsze używaj polecenia task_profiles
do przenoszenia zadań w hierarchiach cgroup. Akceptuje on co najmniej 1 parametr reprezentujący nazwy profili określonych w pliku task_profiles.json
.
Profile zadań na poziomie interfejsu API
W Androidzie 12 i nowszych możesz poprawiać lub zastępować definicje w domyślnych plikach cgroups.json
i task_profiles.json
, korzystając z poziomu interfejsu API Androida lub z partycji dostawcy.
Aby zastąpić definicje na poziomie interfejsu API, na urządzeniu muszą znajdować się te pliki:
/system/etc/task_profiles/cgroups_<API level>.json
Używaj w przypadku grup cgroups specyficznych dla poziomu interfejsu API.
/system/etc/task_profiles/task_profiles_<API level>.json
Używaj tego w przypadku profili związanych z poziomem interfejsu API.
Aby zastąpić definicje z partycji dostawcy, na urządzeniu muszą znajdować się 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ę, do zbioru atrybutów lub profili zostanie dodana nowa definicja.
System Android wczytuje pliki cgroup
i task_profile
w tej kolejności:
- Domyślne pliki
cgroups.json
itask_profiles.json
. - Pliki dotyczące konkretnego poziomu interfejsu API (jeśli istnieją).
- pliki partycji dostawcy, jeśli występują;
Zmiany w dotychczasowym 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 przeniesione do libprocessgroup
, który zawiera teraz wszystkie funkcje związane z cgroup.
Chociaż nagłówek cutils/sched_policy.h
nadal istnieje, aby uniknąć uszkodzenia dotychczasowego kodu, upewnij się, że nowy kod zawiera zamiast niego nowy nagłówek processgroup/sched_policy.h
.
Moduły korzystające z dowolnej z tych funkcji powinny dodać do pliku Makefile zależność od biblioteki libprocessgroup
. Jeśli moduł nie korzysta z żadnej innej funkcji libcutils
, usuń zależność od biblioteki libcutils
z makefile.
Interfejsy API profili zadań
Interfejsy API prywatne w processgroup/processgroup.h
są zdefiniowane w tabeli:
Typ | Interfejs API i definicja |
---|---|
bool |
SetTaskProfiles(int tid, const std::vector
Stosuje profile zadań określone w profiles do wątku określonego przez identyfikator wątku (tid), używając parametru tid . |
bool |
SetProcessProfiles(uid_t uid, pid_t pid, const std::vector
Stosuje profile zadań określone w profiles do procesu określonego przez jego identyfikatory użytkowników i procesów za pomocą parametrów uid i pid |
bool |
CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
Zwraca wartość wskazującą, czy kontroler cgroup określony przez cgroup_name istnieje;
jeśli true , ustawia zmienną path na wartość równą korzeniowi tego cgroup |
bool |
CgroupGetAttributePath(const std::string& attr_name, std::string* path)
Zwraca informację, czy atrybut profilu określony przez parametr attr_name istnieje. Jeśli tak, ustawia zmienną path na ścieżkę do 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 tak, za pomocą parametru tid ustawia zmienną path na ścieżkę pliku powiązanego z tym atrybutem profilu oraz na wątek określony przez jego identyfikator wątku.true |
bool |
UsePerAppMemcg()
Wskazuje, czy system jest skonfigurowany do używania pamięci cgroups dla poszczególnych aplikacji. |