O Android 10 e superior usam uma camada de abstração de grupo de controle (cgroup) com perfis de tarefa, que os desenvolvedores podem usar para descrever um conjunto (ou conjuntos) de restrições a serem aplicadas a um thread ou processo. O sistema então segue as ações prescritas dos perfis de tarefa para selecionar um ou mais cgroups apropriados, por meio dos quais as restrições são aplicadas, e as alterações no conjunto de recursos do cgroup subjacente podem ser feitas sem afetar as camadas de software superiores.
Sobre cgroups
Os Cgroups fornecem um mecanismo para agregar e particionar conjuntos de tarefas (que consistem em processos, threads e todos os seus futuros filhos) em grupos hierárquicos com comportamento especializado. O Android usa cgroups para controlar e contabilizar recursos do sistema, como uso e alocação de CPU e memória, com suporte para cgroups v1 e cgroups v2 do kernel Linux.
Android 9 e inferior
No Android 9 e inferior, o script de inicialização init.rc
continha o conjunto de cgroups disponíveis, seus pontos de montagem e versões. Embora isso possa ser alterado, a estrutura do Android esperava que um conjunto específico de cgroups existisse em locais específicos com uma versão específica e hierarquia de subgrupo, com base no script. Isso limitou a capacidade de escolher a próxima versão do cgroup a ser usada ou de alterar a hierarquia do cgroup para usar novos recursos.
Android 10 e superior
Android 10 e superior usam cgroups com perfis de tarefas:
- Configuração de Cgroup - os desenvolvedores descrevem a configuração de cgroups em seu arquivo
cgroups.json
para definir conjuntos de cgroups e seus locais de montagem e atributos. Todos os cgroups são montados durante o estágio inicial do processo de inicialização. - Perfis de tarefas - fornecem uma abstração que separa a funcionalidade necessária dos detalhes de sua implementação. A estrutura do Android aplica os perfis de tarefa conforme descrito no arquivo
task_profiles.json
a um processo ou encadeamento usando as APIsSetTaskProfiles
eSetProcessProfiles
. (Essas APIs são exclusivas do Android 11 e superior.)
Para fornecer compatibilidade com versões anteriores, as funções legadas set_cpuset_policy
, set_sched_policy
e get_sched_policy
fornecem a mesma API e funcionalidade, mas sua implementação foi modificada para usar perfis de tarefa. Para novos casos de uso, o AOSP recomenda o uso de novas APIs de perfis de tarefas em vez da função herdada set_sched_policy
.
arquivo de descrição do Cgroups
Os Cgroups são descritos no arquivo cgroups.json
localizado em <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
. Cada controlador é descrito em uma subseção e deve ter no mínimo o seguinte:
- Nome, definido pelo campo Controlador .
- Caminho de montagem, definido pelo campo Caminho .
- Mode , UID (ID do usuário) e GID (ID do grupo) descrevendo o proprietário e os modos de acesso para os arquivos neste caminho (todos opcionais).
- Atributo opcional , definido como true para permitir que o sistema ignore o erro de montagem causado por um controlador cgroup que o kernel não suporta ser montado.
Exemplo de arquivo cgroups.json
O exemplo abaixo mostra as descrições dos controladores cgroup v1 ( Cgroups
) e cgroup v2 ( Cgroups2
) com seus respectivos caminhos.
{
"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"
}
]
}
}
Este arquivo de exemplo contém duas seções, Cgroups (descrevendo os controladores cgroup v1) e Cgroups2 (descrevendo os controladores cgroup v2). Todos os controladores na hierarquia do cgroups v2 são montados no mesmo local. Portanto, a seção Cgroups2 tem seus próprios atributos Path , Mode , UID e GID para descrever o local e os atributos da raiz da hierarquia. O atributo Path para Controllers em Cgroups2 é relativo a esse caminho raiz. No Android 12 e superior, você pode definir um controlador cgroup especificado com path e mode como "Optional"
definindo-o como true
.
O arquivo cgroups.json
é analisado como parte do processo de inicialização, durante o estágio inicial, e os cgroups são montados nos locais especificados. Para obter posteriormente os locais de montagem do cgroup, use a função da API CgroupGetControllerPath
.
Arquivo de perfis de tarefa
O arquivo task_profiles.json
está localizado em <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
. Use-o para descrever um conjunto específico de ações a serem aplicadas a um processo ou encadeamento. Um conjunto de ações é associado a um nome de perfil, que é usado em chamadas SetTaskProfiles
e SetProcessProfiles
para invocar ações de perfil.
Exemplo de arquivo 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" ]
}
}
Atribua nomes a arquivos cgroup específicos como entradas em sua lista de atributos . Cada entrada contém o seguinte:
- Campo Nome - especifica o nome do Atributo.
- Campo Controller - referencia um controlador cgroup do arquivo
cgroups.json
, por seu nome. - Campo de arquivo - nomeia um arquivo específico sob este controlador.
Atributos são referências em definições de perfil de tarefa. Fora dos perfis de tarefa, use-os apenas quando a estrutura exigir acesso direto a esses arquivos e o acesso não puder ser abstraído usando perfis de tarefa. Em todos os outros casos, use perfis de tarefa; eles fornecem melhor desacoplamento entre o comportamento necessário e seus detalhes de implementação.
A seção Perfis contém definições de perfil de tarefa com o seguinte:
- Campo Nome - define o nome do perfil.
Seção de ações - lista um conjunto de ações executadas quando o perfil é aplicado. Cada ação tem o seguinte:
- Campo de nome que especifica a ação
- Seção de parâmetros especificando um conjunto de parâmetros para a ação
As ações com suporte estão listadas na tabela abaixo.
Açao | Parâmetro | Descrição |
---|---|---|
SetTimerSlack | Slack | Folga do temporizador em ns |
SetAttribute | Name | Um nome que faz referência a um atributo da seção Atributos | Value | Um valor a ser gravado no arquivo representado pelo atributo nomeado |
WriteFile | FilePath | caminho para o arquivo | Value | um valor a ser gravado no arquivo |
JoinCgroup | Controller | Um nome do controlador cgroup de cgroups.json |
Path | Um caminho de subgrupo na hierarquia do controlador cgroup |
O Android 12 e superior apresentam uma seção AggregateProfiles que contém perfis agregados, cada um dos quais é um alias para um conjunto de um ou mais perfis. As definições de perfil agregadas consistem no seguinte:
- Campo Nome - especifica o nome do perfil agregado.
- Campo Perfis - lista os nomes dos perfis incluídos no perfil agregado.
Quando um perfil agregado é aplicado, todos os perfis contidos também são aplicados automaticamente. Os perfis agregados podem conter perfis individuais ou outros perfis agregados, desde que não haja recursões (um perfil que inclui a si mesmo).
comando de linguagem de inicialização task_profiles
Um comando task_profiles
no Android Init Language está disponível para Android 12 e superior para facilitar a ativação do perfil de tarefa para um processo específico. Ele substitui o comando writepid
(obsoleto no Android 12) que foi usado para migrar um processo entre cgroups. O comando task_profiles
fornece flexibilidade para alterar implementações subjacentes sem nenhum efeito nas camadas superiores. No exemplo abaixo, esses dois comandos executam efetivamente a mesma operação:
writepid /dev/cpuctl/top-app/tasks
Obsoleto no Android 12 - Foi usado para gravar o PID da tarefa atual no
/dev/cpuctl/top-app/tasks
.task_profiles MaxPerformance
Junta o processo atual ao grupo top-app no controlador "cpu" (
cpuctl
), o que resulta na gravação do PID do processo emdev/cpuctl/top-app/tasks
.
Sempre use o comando task_profiles
para migrar tarefas em hierarquias de cgroup no Android 12 e superior. Ele aceita um ou mais parâmetros, representando os nomes dos perfis especificados no arquivo task_profiles.json
.
Por perfis de tarefa no nível da API
No Android 12 e superior, você pode alterar ou substituir as definições nos arquivos cgroups.json
e task_profiles.json
padrão, baseando sua alteração no nível da API do Android ou fazendo-a a partir da partição do fornecedor.
Para substituir as definições com base no nível da API, os seguintes arquivos devem estar presentes no dispositivo:
pro/system/etc/task_profiles/cgroups_<API level>.json
Use isso para cgroups específicos para um nível de API.
/system/etc/task_profiles/task_profiles_<API level>.json
Use isso para perfis específicos para um nível de API.
Para substituir as definições da partição do fornecedor, os seguintes arquivos devem estar presentes no dispositivo:
-
/vendor/etc/cgroups.json
-
/vendor/etc/task_profiles.json
Se um atributo ou uma definição de perfil nesses arquivos usar o mesmo nome que está no arquivo padrão, a definição do arquivo (nível de API ou nível de fornecedor) substituirá a definição anterior. Observe também que as definições no nível do fornecedor substituem as definições no nível da API. Se a nova definição tiver um novo nome, o conjunto de atributos ou perfis será alterado com a nova definição.
O sistema Android carrega os arquivos cgroup
e task_profile
nesta ordem:
-
cgroups.json
etask_profiles.json
padrão. - Arquivos específicos do nível da API, se presentes.
- Arquivos de partição do fornecedor, se houver.
Alterações na API existente
O Android 10 e superior mantém as funções set_cpuset_policy
, set_sched_policy
e get_sched_policy
sem alterações na API. No entanto, o Android 10 move essas funções para libprocessgroup
, que agora contém todas as funcionalidades relacionadas ao cgroup.
Embora o cabeçalho cutils/sched_policy.h
ainda exista, para evitar quebrar o código existente, certifique-se de que o novo código inclua um novo cabeçalho processgroup/sched_policy.h
.
Módulos que usam qualquer uma dessas funções devem adicionar dependência da biblioteca libprocessgroup
em seu makefile. Se um módulo não usa nenhuma outra funcionalidade libcutils
, elimine a dependência da biblioteca libcutils
do makefile.
APIs de perfis de tarefas
As APIs privadas em processgroup/processgroup.h
são definidas na tabela abaixo:
Tipo | API e definição |
---|---|
bool | SetTaskProfiles(int tid, const std::vector & profiles) SetTaskProfiles(int tid, const std::vector & profiles) Aplica os perfis de tarefa especificados em |
bool | SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles) SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles) Aplica os perfis de tarefa especificados em |
bool | CgroupGetControllerPath(const std::string& cgroup_name, std::string* path) Retorna se existe um controlador cgroup especificado por |
bool | CgroupGetAttributePath(const std::string& attr_name, std::string* path) Retorna se existe um atributo de perfil especificado por |
bool | CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path) Retorna se existe um atributo de perfil especificado por |
bool | UsePerAppMemcg() Retorna se o sistema está configurado para usar cgroups de memória por aplicativo. |