Livello di astrazione Cgroup

Android 10 e versioni successive utilizzano un livello di astrazione del gruppo di controllo (cgroup) con profili di attività, che gli sviluppatori possono utilizzare per descrivere una serie (o serie) di restrizioni da applicare a un thread o a un processo. Il sistema segue quindi le azioni prescritte dai profili di attività per selezionare uno o più cgroup appropriati, attraverso i quali vengono applicate le restrizioni e le modifiche al set di funzionalità del cgroup sottostante possono essere apportate senza influenzare i livelli software superiori.

A proposito di cgroup

I Cgroup forniscono un meccanismo per aggregare e partizionare insiemi di attività (che consistono in processi, thread e tutti i loro futuri figli) in gruppi gerarchici con comportamento specializzato. Android utilizza i cgroup per controllare e tenere conto delle risorse di sistema come l'utilizzo e l'allocazione della CPU e della memoria, con il 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 dei cgroup disponibili, i relativi punti di montaggio e le versioni. Sebbene questi potessero essere modificati, il framework Android prevedeva l'esistenza di un insieme specifico di cgroup in posizioni specifiche con una versione specifica e una gerarchia di sottogruppi, basata sullo script. Ciò limitava la possibilità di scegliere la successiva versione di cgroup da utilizzare o di modificare la gerarchia di cgroup per utilizzare nuove funzionalità.

Android 10 e versioni successive

Android 10 e versioni successive utilizzano cgroup con profili attività:

  • Configurazione di Cgroup: gli sviluppatori descrivono la configurazione di cgroup nel file cgroups.json per definire set di cgroup e le relative posizioni e attributi di montaggio. Tutti i cgroup vengono montati durante la fase iniziale del processo di inizializzazione.
  • Profili di attività: forniscono un'astrazione che disaccoppia la funzionalità richiesta dai dettagli della sua implementazione. Il framework Android applica i profili di attività come descritto nel file task_profiles.json a un processo o thread utilizzando le API SetTaskProfiles e SetProcessProfiles . (Queste API sono esclusive 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 di attività. Per i nuovi casi d'uso, AOSP consiglia di utilizzare le nuove API dei profili di attività anziché la funzione legacy set_sched_policy .

File di descrizione di Cgroups

I Cgroup sono descritti nel file cgroups.json situato in <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ . Ciascun 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 opzionale , impostato su true per consentire al sistema di ignorare l'errore di montaggio causato da un controller cgroup di cui il kernel non supporta il montaggio.

File cgroups.json di esempio

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 per la radice della gerarchia. L'attributo Path per i controller in Cgroups2 è relativo a quel percorso root. 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 inizializzazione, durante la fase iniziale, e i cgroup vengono montati nelle posizioni specificate. Per ottenere successivamente le posizioni di montaggio del cgroup, utilizzare la funzione API CgroupGetControllerPath .

File dei profili delle attività

Il file task_profiles.json si trova in <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ . Usalo per descrivere un insieme specifico di azioni da applicare a un processo o un thread. Una serie di azioni è associata a un nome di 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:

  • Campo Nome : specifica il nome dell'Attributo.
  • Campo controller : fa riferimento a un controller cgroup dal file cgroups.json , tramite il suo nome.
  • Campo file : nomina un file specifico sotto questo controller.

Gli attributi sono riferimenti nelle definizioni del profilo dell'attività. Al di fuori dei profili di attività, usarli solo quando il framework richiede l'accesso diretto a tali file e l'accesso non può essere astratto utilizzando i profili di attività. In tutti gli altri casi, utilizzare i profili attività; forniscono un migliore disaccoppiamento tra il comportamento richiesto e i suoi dettagli di implementazione.

La sezione Profili contiene le definizioni dei profili di attività con quanto segue:

  • Campo Nome : definisce il nome del profilo.
  • Sezione Azioni : elenca una serie di azioni eseguite quando viene applicato il profilo. Ogni azione ha quanto segue:

    • Campo del nome che specifica l'azione
    • Sezione Params che specifica un set di parametri per l'azione

Le azioni supportate sono elencate nella tabella seguente.

Azione Parametro Descrizione
SetTimerSlack Slack Temporizzatore allentato in ns
SetAttribute Name Un nome che fa riferimento a un attributo dalla 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 di sottogruppo nella gerarchia del controller cgroup

Android 12 e versioni successive presentano una sezione AggregateProfiles che contiene profili aggregati, ognuno dei quali è un alias per un set di uno o più profili. Le definizioni del profilo aggregato sono costituite da quanto segue:

  • Campo Nome : specifica il nome del profilo aggregato.
  • Campo Profili : elenca i nomi dei profili inclusi nel profilo aggregato.

Quando viene applicato un profilo aggregato, vengono applicati automaticamente anche tutti i profili che lo contengono. I profili aggregati possono contenere sia profili individuali che altri profili aggregati, purché non siano presenti ricorsioni (un profilo che include se stesso).

comando del linguaggio init task_profiles

Un comando task_profiles in Android Init Language è disponibile per Android 12 e versioni successive per facilitare l'attivazione del profilo attività per un processo specifico. Sostituisce il comando writepid (obsoleto in Android 12) utilizzato per migrare un processo tra cgroup. Il comando task_profiles fornisce flessibilità per modificare le implementazioni sottostanti senza alcun effetto sui livelli superiori. Nell'esempio seguente, questi due comandi eseguono effettivamente la stessa operazione:

  • writepid /dev/cpuctl/top-app/tasks

    Deprecato in Android 12: 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 top-app sotto il controller "cpu" ( cpuctl ), il che comporta la scrittura del PID del processo su dev/cpuctl/top-app/tasks .

Utilizza sempre il comando task_profiles per migrare le 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 API

In Android 12 e versioni successive, puoi modificare o sovrascrivere le definizioni nei file cgroups.json e task_profiles.json predefiniti, basando la modifica sul livello API Android o effettuandola dalla partizione del fornitore.

Per sovrascrivere le definizioni in base al livello API, sul dispositivo devono essere presenti i seguenti file:

  • pro/system/etc/task_profiles/cgroups_<API level>.json

    Usalo per cgroup specifici a livello API.

  • /system/etc/task_profiles/task_profiles_<API level>.json

    Utilizzalo per profili specifici a un livello API.

Per sovrascrivere le definizioni dalla 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 del file predefinito, la definizione del file (a livello API o fornitore) sovrascrive la definizione precedente. Tieni inoltre presente che le definizioni a livello di fornitore sovrascrivono le definizioni 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:

  1. File cgroups.json e task_profiles.json predefiniti.
  2. File specifici del livello API, se presenti.
  3. 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 a cgroup.

Sebbene l'intestazione cutils/sched_policy.h esista ancora, per evitare di danneggiare il codice esistente assicurati che il nuovo codice includa invece una nuova intestazione processgroup/sched_policy.h .

I moduli che utilizzano una qualsiasi di queste funzioni dovrebbero aggiungere la dipendenza dalla libreria libprocessgroup nel loro makefile. Se un modulo non utilizza nessun'altra funzionalità libcutils , elimina la dipendenza della libreria libcutils dal makefile.

API dei profili di attività

Le API private in processgroup/processgroup.h sono definite nella tabella seguente:

Tipo API e definizione
bool SetTaskProfiles(int tid, const std::vector & profiles) SetTaskProfiles(int tid, const std::vector & profiles)

Applica i profili di attività specificati nei 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 & profiles) SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles)

Applica i profili di attività specificati nei profiles al processo specificato dall'utente e dagli ID di processo utilizzando i parametri uid e pid

bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)

Restituisce 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 tale 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 true , imposta la variabile path sul percorso del file associato a tale attributo del profilo e sul thread specificato dal relativo ID thread utilizzando il parametro tid .

bool UsePerAppMemcg()

Restituisce se il sistema è configurato per utilizzare cgroup di memoria per applicazione.