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ù cgroups appropriati, attraverso i quali vengono applicate limitazioni, ed è possibile apportare modifiche al set di funzionalità cgroup sottostante senza influire sui livelli software più elevati.
Informazioni sui gruppi c
I gruppi C forniscono un meccanismo per aggregare e suddividere insiemi di attività (costituito da processi, thread e tutti i relativi processi secondari futuri) in gruppi gerarchici con comportamento specializzato. Android utilizza cgroups per controllare e tenere conto delle risorse di sistema, come l'utilizzo e l'allocazione di CPU e memoria, con il supporto di 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. Sebbene questi possano essere modificati, il framework Android si aspettava che esistesse un insieme specifico di cgroups in posizioni specifiche con una versione e una gerarchia di sottogruppi specifici, in base allo script. Ciò limitava la possibilità di scegliere la versione successiva di cgroup da utilizzare o di cambiare la gerarchia di cgroup per utilizzare nuove funzionalità.
Android 10 e versioni successive
Android 10 e versioni successive utilizzano i gruppi cgroup con profili di attività:
- Configurazione del gruppo C. Gli sviluppatori descrivono la configurazione dei gruppi di contenitori nel file
cgroups.json
per definire insiemi di gruppi di contenitori, le relative posizioni di montaggio e gli attributi. Tutti i gruppi cgroup vengono montati durante la fase di inizializzazione iniziale del processo di inizializzazione. - Profili delle attività. Forniscono un'astrazione che disaccoppia la funzionalità richiesta dai dettagli della sua implementazione. Il framework Android applica i profili delle attività descritti nel file
task_profiles.json
a un processo o a un thread utilizzando le APISetTaskProfiles
eSetProcessProfiles
. (Queste API sono uniche per Android 11 e versioni successive).
Per garantire la compatibilità con le versioni precedenti, le funzioni precedenti 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
precedente.
File di descrizione dei gruppi cgroup
I gruppi C 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 Path.
- Modalità, 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 gestori 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 Path per Controllers in Cgroups2 è relativo a questo percorso principale. 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 come parte del processo di init, durante la fase di inizializzazione anticipata, e i gruppi cgroups vengono montati nelle posizioni specificate. Per ottenere in un secondo momento le posizioni di montaggio del cgroup, utilizza la funzione dell'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. A un nome profilo è associato un insieme di azioni, che viene utilizzato nelle chiamate SetTaskProfiles
e SetProcessProfiles
per richiamare le azioni del profilo.
File task_profile.json di esempio
{
"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 Name (Nome) specifica il nome dell'attributo.
- Il campo Controller fa riferimento a un controller cgroup dal file
cgroups.json
, con il nome. - Il campo File consente di assegnare un nome a un file specifico all'interno di 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 consentono un disaccoppiamento migliore tra il comportamento richiesto e i dettagli di implementazione.
La sezione Profili contiene le definizioni dei profili delle attività con le seguenti definizioni:
- Il campo Nome definisce il nome del profilo.
La sezione Azioni elenca un insieme di azioni eseguite quando il profilo viene applicato. Ogni azione ha i seguenti elementi:
- 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 |
Tempo di attesa del timer 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 |
Il nome del controller cgroup di cgroups.json |
Path |
Percorso di un sottogruppo nella gerarchia del controller cgroup |
Android 12 e versioni successive includono una sezione AggregateProfiles che contiene profili aggregati, ciascuno dei quali è un alias per un insieme di uno o più profili. Le definizioni dei profili aggregati sono costituite da:
- Il campo Nome specifica il nome del profilo aggregato.
- Il campo Profiles (Profili) elenca i nomi dei profili inclusi nel profilo aggregato.
Quando viene applicato un profilo aggregato, vengono applicati automaticamente anche tutti i profili contenenti. I profili aggregati possono contenere sia profili singoli o altri profili aggregati, a condizione che non siano presenti ricorsioni (ovvero un profilo che si include).
Comando task_profiles init language
Un comando task_profiles
in Android Init Language
è disponibile per Android 12 e versioni successive per facilitare
l'attivazione del profilo delle attività per un processo specifico. Sostituisce il comando writepid
(deprecato in Android 12) utilizzato per eseguire la migrazione di un
procedura tra i cgroups. Il comando task_profiles
offre flessibilità per cambiare le implementazioni sottostanti senza alcun effetto sui livelli superiori. Nell'esempio riportato di seguito, questi due comandi eseguono effettivamente la stessa operazione:
writepid /dev/cpuctl/top-app/tasks
Ritirata in Android 12, veniva utilizzata 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
), con la conseguente scrittura del PID del processo indev/cpuctl/top-app/tasks
.
Usa 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 sostituire le definizioni nei file cgroups.json
e task_profiles.json
predefiniti, basando la modifica sul livello dell'API Android o eseguendola dalla partizione del fornitore.
Per eseguire l'override delle definizioni in base al livello API, sul dispositivo devono essere presenti i seguenti file:
/system/etc/task_profiles/cgroups_<API level>.json
Utilizzalo per i gruppi cgroup specifici per un livello API.
/system/etc/task_profiles/task_profiles_<API level>.json
Utilizzalo per i profili specifici per un livello API.
Per eseguire l'override delle definizioni della partizione del fornitore, sul dispositivo devono essere presenti i seguenti file:
/vendor/etc/cgroups.json
/vendor/etc/task_profiles.json
Se un attributo o una definizione di profilo in questi file utilizza lo stesso nome di quello nel file predefinito, la definizione del file (a livello di API o di fornitore) sostituisce la definizione precedente. Tieni inoltre presente che le definizioni a livello di fornitore hanno la precedenza su 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, in Android 10 queste funzioni vengono spostate in
libprocessgroup
, che ora contiene tutte le funzionalità relative ai gruppi cgroup.
Sebbene l'intestazione cutils/sched_policy.h
esista ancora, per evitare di interrompere il codice esistente, assicurati che il nuovo codice includa invece una nuova intestazione processgroup/sched_policy.h
.
I moduli che utilizzano una di queste funzioni devono aggiungere la dipendenza dalla libreria libprocessgroup
al proprio file make. Se un modulo non utilizza altre funzionalità
libcutils
, rimuovi la dipendenza della libreria libcutils
dal file make.
API per i profili delle attività
Le API private in processgroup/processgroup.h
sono definite nella tabella:
Digitazione | 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 relativo parametro tid . |
bool |
SetProcessProfiles(uid_t uid, pid_t pid, const std::vector
Applica i profili delle attività specificati in profiles al processo specificato
tramite gli ID utente e processo utilizzando i parametri uid e pid |
bool |
CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
Indica se esiste un controller cgroup specificato da cgroup_name ;
se true , imposta la variabile path sulla radice di quel cgroup |
bool |
CgroupGetAttributePath(const std::string& attr_name, std::string* path)
Restituisce 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 se esiste un attributo del profilo specificato da attr_name . Se il valore è true , imposta la variabile path sul percorso del file associato a quell'attributo del profilo e sul thread specificato dal relativo ID thread utilizzando il parametro tid . |
bool |
UsePerAppMemcg()
Restituisce se il sistema è configurato per utilizzare i gruppi di controllo della memoria per app. |