Livello di astrazione Cgroup

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 API SetTaskProfiles e SetProcessProfiles. (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
WriteFileFilePathpercorso del file
Valueun 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 in dev/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:

  1. File cgroups.json e task_profiles.json predefiniti.
  2. File specifici per il 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, 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& profiles)
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& profiles)
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.