Android 10 e versioni successive utilizzano un livello di astrazione del gruppo di controllo (cgroup) con profili delle attività, che gli sviluppatori possono utilizzare per descrivere un insieme (o insiemi) di limitazioni da applicare a un thread o a un processo. Il sistema segue quindi le azioni prescritte dei profili delle attività per selezionare uno o più cgroup appropriati, tramite i quali vengono applicate le limitazioni e possono essere apportate modifiche al set di funzionalità cgroup sottostante senza influire sui livelli software superiori.
Informazioni sui cgroup
I cgroup forniscono un meccanismo per aggregare e partizionare insiemi di attività (che consistono in processi, thread e tutti i loro elementi secondari futuri) in gruppi gerarchici con un comportamento specializzato. Android utilizza cgroups per controllare e contabilizzare le risorse di sistema come l'utilizzo e l'allocazione di CPU e memoria, con supporto per cgroups v1 e cgroups v2 del kernel Linux.
Android 9 e versioni precedenti
In Android 9 e versioni precedenti, lo script di inizializzazione init.rc
conteneva l'insieme di
cgroup disponibili, i relativi punti di montaggio e le versioni. Anche se questi potrebbero essere
modificati, il framework Android prevedeva che esistesse un insieme specifico di cgroup in
posizioni specifiche con una versione e una gerarchia di sottogruppi specifiche, in base allo
script. Ciò ha limitato la possibilità di scegliere la successiva versione di cgroup da utilizzare o di
modificare la gerarchia cgroup per utilizzare nuove funzionalità.
Android 10 e versioni successive
Android 10 e versioni successive utilizzano i cgroup con i profili delle attività:
- Configurazione del gruppo di controllo. Gli sviluppatori descrivono la configurazione dei cgroup nel file
cgroups.json
per definire i set di cgroup, le relative posizioni di montaggio e gli attributi. Tutti i cgroup vengono montati durante la fase di inizializzazione iniziale del processo di inizializzazione. - Profili delle attività. Questi forniscono un'astrazione che disaccoppia la funzionalità richiesta dai dettagli della sua implementazione. Il framework Android
applica i profili delle attività come descritto nel file
task_profiles.json
a un processo o thread utilizzando le APISetTaskProfiles
eSetProcessProfiles
. Queste API sono specifiche di Android 11 e versioni successive.
Per garantire la compatibilità con le versioni precedenti, le funzioni legacy set_cpuset_policy
,
set_sched_policy
e get_sched_policy
forniscono la stessa API e funzionalità,
ma la loro implementazione è stata modificata per utilizzare i profili delle attività. Per i nuovi casi d'uso, AOSP consiglia di utilizzare le nuove API dei profili delle attività anziché la funzione set_sched_policy
legacy.
File di descrizione dei cgroup
I cgroup sono descritti nel file cgroups.json
che si trova in <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Ogni controller è descritto in una sottosezione e deve avere almeno quanto segue:
- Nome, definito dal campo Controller.
- Percorso di montaggio, definito dal campo Percorso.
- Mode, UID (ID utente) e GID (ID gruppo) che descrivono il proprietario e le modalità di accesso per i file in questo percorso (tutti facoltativi).
- Attributo facoltativo, impostato su true per consentire al sistema di ignorare l'errore di montaggio causato da un controller cgroup che il kernel non supporta.
Esempio di file cgroups.json
L'esempio seguente mostra le descrizioni dei controller cgroup v1 (Cgroups
) e cgroup v2
(Cgroups2
) con i rispettivi percorsi.
{
"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"
}
]
}
}
Questo file di esempio contiene due sezioni: Cgroups (che descrive i controller cgroup v1) e Cgroups2 (che descrive i controller cgroup v2). Tutti
i controller nella gerarchia cgroups v2 sono montati nella stessa posizione.
Pertanto, la sezione Cgroups2 ha i propri attributi Path, Mode, UID e
GID per descrivere la posizione e gli attributi della radice della
gerarchia. L'attributo Percorso per Controller in Cgroups2 è
relativo a quel percorso radice. In Android 12 e versioni successive puoi definire un controller cgroup
specificato con percorso e modalità come "Optional"
impostandolo su true
.
Il file cgroups.json
viene analizzato nell'ambito del processo di inizializzazione, durante la fase di inizializzazione
iniziale, e i cgroup vengono montati nelle posizioni specificate. Per ottenere in un secondo momento
le posizioni di montaggio del cgroup, utilizza la funzione API CgroupGetControllerPath
.
File dei profili delle attività
Il file task_profiles.json
si trova in <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Utilizzalo per descrivere un insieme specifico di azioni da applicare a un processo o a un
thread. Un insieme di azioni è associato a un nome profilo, che viene utilizzato nelle chiamate
SetTaskProfiles
e SetProcessProfiles
per richiamare le azioni del profilo.
Esempio di file 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" ]
}
}
Assegna nomi a file cgroup specifici come voci nell'elenco Attributi. Ogni voce contiene quanto segue:
- Il campo Nome specifica il nome dell'attributo.
- Il campo Controller fa riferimento a un controller cgroup del file
cgroups.json
in base al nome. - Il campo File indica un file specifico in questo controller.
Gli attributi sono riferimenti nelle definizioni dei profili delle attività. Al di fuori dei profili delle attività, utilizzali solo quando il framework richiede l'accesso diretto a questi file e l'accesso non può essere astratto utilizzando i profili delle attività. In tutti gli altri casi, utilizza i profili delle attività, che forniscono un migliore disaccoppiamento tra il comportamento richiesto e i dettagli della sua implementazione.
La sezione Profili contiene le definizioni dei profili delle attività con quanto segue:
- Il campo Nome definisce il nome del profilo.
La sezione Azioni elenca un insieme di azioni eseguite quando viene applicato il profilo. Ogni azione ha quanto segue:
- Il campo Nome specifica l'azione.
- La sezione Params specifica un insieme di parametri per l'azione.
Le azioni supportate sono elencate nella tabella:
Azione | Parametro | Descrizione |
---|---|---|
SetTimerSlack |
Slack |
Timer slack in ns |
SetAttribute |
Name |
Un nome che fa riferimento a un attributo della sezione Attributi |
Value |
Un valore da scrivere nel file rappresentato dall'attributo denominato | |
WriteFile | FilePath | percorso del file |
Value | un valore da scrivere nel file | |
JoinCgroup |
Controller |
Un nome del controller cgroup da cgroups.json |
Path |
Un percorso del sottogruppo nella gerarchia del controller cgroup |
Android 12 e versioni successive includono una sezione AggregateProfiles che contiene profili aggregati, ognuno dei quali è un alias per un insieme di uno o più profili. Le definizioni di profilo aggregate sono costituite da:
- Il campo Nome specifica il nome del profilo aggregato.
- Il campo Profili elenca i nomi dei profili inclusi nel profilo aggregato.
Quando viene applicato un profilo aggregato, vengono applicati automaticamente anche tutti i profili contenuti. I profili aggregati possono contenere sia profili individuali sia altri profili aggregati, purché non ci siano ricorsioni (un profilo che include se stesso).
task_profiles init language command
Un comando task_profiles
nel linguaggio di inizializzazione di Android
è disponibile per Android 12 e versioni successive per facilitare
l'attivazione del profilo attività per un processo specifico. Sostituisce il comando writepid
(deprecato in Android 12) utilizzato per eseguire la migrazione di un
processo tra i cgroup. Il comando task_profiles
offre flessibilità per
modificare le implementazioni sottostanti senza influire sui livelli superiori. Nell'esempio
che segue, questi due comandi eseguono effettivamente la stessa operazione:
writepid /dev/cpuctl/top-app/tasks
Deprecato in Android 12, questo valore veniva utilizzato per scrivere il PID dell'attività corrente nel file
/dev/cpuctl/top-app/tasks
.task_profiles MaxPerformance
Unisce il processo corrente al gruppo di app principali nel controller "cpu" (
cpuctl
), il che comporta la scrittura del PID del processo indev/cpuctl/top-app/tasks
.
Utilizza sempre il comando task_profiles
per eseguire la migrazione delle attività nelle gerarchie cgroup in
Android 12 e versioni successive. Accetta uno o più parametri, che rappresentano i
nomi dei profili specificati nel file task_profiles.json
.
Per profili di attività a livello di API
In Android 12 e versioni successive, puoi modificare o ignorare
le definizioni nei file cgroups.json
e task_profiles.json
predefiniti, basando la modifica sul livello API Android o apportandola dalla partizione del fornitore.
Per eseguire l'override delle definizioni in base al livello API, i seguenti file devono essere presenti sul dispositivo:
/system/etc/task_profiles/cgroups_<API level>.json
Utilizza questa opzione per i cgroup specifici per un livello API.
/system/etc/task_profiles/task_profiles_<API level>.json
Utilizza questo campo per i profili specifici per un livello API.
Per eseguire l'override delle definizioni della partizione del fornitore, i seguenti file devono essere presenti sul dispositivo:
/vendor/etc/cgroups.json
/vendor/etc/task_profiles.json
Se un attributo o una definizione di profilo in questi file utilizza lo stesso nome del file predefinito, la definizione del file (a livello di API o fornitore) sostituisce la definizione precedente. Tieni presente inoltre che le definizioni a livello di fornitore sostituiscono quelle a livello di API. Se la nuova definizione ha un nuovo nome, l'insieme di attributi o profili viene modificato con la nuova definizione.
Il sistema Android carica i file cgroup
e task_profile
in questo ordine:
- File
cgroups.json
etask_profiles.json
predefiniti. - File specifici per il livello API, se presenti.
- File di partizione del fornitore, se presenti.
Modifiche all'API esistente
Android 10 e versioni successive mantengono le funzioni set_cpuset_policy
,
set_sched_policy
e get_sched_policy
senza modifiche all'API.
Tuttavia, Android 10 sposta queste funzioni in
libprocessgroup
, che ora contiene tutte le funzionalità relative ai cgroup.
Sebbene l'intestazione cutils/sched_policy.h
esista ancora, per evitare di interrompere
il codice esistente, assicurati che il nuovo codice includa una nuova intestazione processgroup/sched_policy.h
.
I moduli che utilizzano una di queste funzioni devono aggiungere la dipendenza dalla
libreria libprocessgroup
nel proprio makefile. Se un modulo non utilizza altre funzionalità di libcutils
, rimuovi la dipendenza della libreria libcutils
dal makefile.
API dei profili delle attività
Le API private in processgroup/processgroup.h
sono definite nella tabella:
Tipo | API e definizione |
---|---|
bool |
SetTaskProfiles(int tid, const std::vector
Applica i profili delle attività specificati in profiles al thread specificato da
un ID thread (tid) utilizzando il parametro tid . |
bool |
SetProcessProfiles(uid_t uid, pid_t pid, const std::vector
Applica i profili delle attività specificati in profiles al processo specificato
dai relativi ID utente e processo utilizzando i parametri uid e pid |
bool |
CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
Restituisce un valore che indica se esiste un controller cgroup specificato da cgroup_name ;
se true , imposta la variabile path sulla radice del cgroup |
bool |
CgroupGetAttributePath(const std::string& attr_name, std::string* path)
Restituisce un valore che indica se esiste un attributo del profilo specificato da attr_name ; se
true , imposta la variabile path sul percorso del file associato
a quell'attributo del profilo. |
bool |
CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)
Restituisce un valore che indica se esiste un attributo del profilo specificato da attr_name ; se
true , imposta la variabile path sul percorso del file associato
a quell'attributo del profilo e al thread specificato dal relativo ID thread utilizzando
il parametro tid . |
bool |
UsePerAppMemcg()
Restituisce un valore che indica se il sistema è configurato per utilizzare i cgroup di memoria per app. |