O Android 10 e versões mais recentes usam uma camada de abstração de grupo de controle (cgroup) com perfis de tarefas, que os desenvolvedores podem usar para descrever um conjunto (ou conjuntos) de restrições a serem aplicadas a uma linha de execução ou a um processo. Em seguida, o sistema segue as ações prescritas dos perfis de tarefas para selecionar um ou mais cgroups apropriados, em que as restrições são aplicadas, e as mudanças no conjunto de recursos de cgroup podem ser feitas sem afetar camadas de software mais altas.
Sobre os cgroups
Os grupos C fornecem um mecanismo para agregar e particionar conjuntos de tarefas (que consistem em processos, linhas de execução e todos os filhos futuros) 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 do Linux.
Android 9 e versões anteriores
No Android 9 e versões anteriores, o script de inicialização init.rc
continha o conjunto de
cgroups disponíveis, os pontos de montagem e as versões. Embora isso pudesse
ser alterado, o framework do Android esperava que um conjunto específico de cgroups existisse em
locais específicos com uma versão e hierarquia de subgrupos específica, com base no
script. Isso limitou a capacidade de escolher a próxima versão do cgroup a ser usada ou
mudar a hierarquia do cgroup para usar novos recursos.
Android 10 e versões mais recentes
O Android 10 e versões mais recentes usam cgroups com perfis de tarefas:
- Configuração de grupos. Os desenvolvedores descrevem a configuração de cgroups no arquivo
cgroups.json
para definir conjuntos de cgroups e os atributos e locais de montagem deles. Todos os cgroups são montados durante a fase inicial do processo de inicialização. - Perfis de tarefas. Elas fornecem uma abstração que separa a funcionalidade
necessária dos detalhes da implementação. O framework do Android
aplica os perfis de tarefas, conforme descrito no arquivo
task_profiles.json
, a um processo ou linha de execução usando as APIsSetTaskProfiles
eSetProcessProfiles
. Essas APIs são exclusivas do Android 11 e versões mais recentes.
Para oferecer compatibilidade com versões anteriores, as funções set_cpuset_policy
,
set_sched_policy
e get_sched_policy
legadas oferecem a mesma API e funcionalidade,
mas a implementação delas foi modificada para usar perfis de tarefas. Para novos casos
de uso, o AOSP recomenda usar novas APIs de perfil de tarefas em vez da função
set_sched_policy
legada.
Arquivo de descrição de cgroups
Os grupos C são descritos no arquivo cgroups.json
localizado em <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Cada controlador é descrito em uma subseção e precisa 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) que descrevem o proprietário e os modos de acesso para os arquivos nesse caminho (todos opcionais).
- Atributo Opcional, definido como true para permitir que o sistema ignore o erro de montagem causado por um controlador de cgroup que o kernel não oferece suporte para montagem.
Exemplo de arquivo cgroups.json
O exemplo abaixo mostra descrições para controladores cgroup v1 (Cgroups
) e cgroup v2
(Cgroups2
) com os 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 (que descreve os controladores cgroup v1) e Cgroups2 (que descreve os controladores cgroup v2). Todos
os controladores na hierarquia de 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 a localização e os atributos da raiz da hierarquia. O atributo Path para Controllers em Cgroups2 é
relativo a esse caminho raiz. No Android 12 e versões mais recentes, é possível definir um controlador de cgroup
especificado com caminho e modo como "Optional"
definindo-o como true
.
O arquivo cgroups.json
é analisado como parte do processo de inicialização, durante a fase inicial
de inicialização, e os cgroups são montados nos locais especificados. Para acessar
os locais de montagem do cgroup mais tarde, use a função da API CgroupGetControllerPath
.
Arquivo de perfis de tarefas
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 a
uma linha de execução. 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 na lista de Atributos. Cada entrada contém o seguinte:
- O campo Nome especifica o nome do atributo.
- O campo controller faz referência a um controlador de cgroup do arquivo
cgroups.json
pelo nome. - O campo File nomeia um arquivo específico neste controlador.
Os atributos são referências nas definições de perfil de tarefas. Fora dos perfis de tarefas, use-os somente quando o framework exigir acesso direto a esses arquivos e o acesso não puder ser abstrato usando perfis de tarefas. Em todos os outros casos, use perfis de tarefas. Eles oferecem um melhor desacoplamento entre o comportamento necessário e os detalhes de implementação.
A seção Perfis contém definições de perfil de tarefas com o seguinte:
- O campo Name define o nome do perfil.
A seção Ações lista um conjunto de ações realizadas quando o perfil é aplicado. Cada ação tem o seguinte:
- O campo Nome especifica a ação.
- A seção Params especifica um conjunto de parâmetros para a ação.
As ações compatíveis estão listadas na tabela:
Ação | Parâmetro | Descrição |
---|---|---|
SetTimerSlack |
Slack |
Tempo de espera do timer 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 de cgroup de cgroups.json |
Path |
Um caminho de subgrupo na hierarquia do controlador de cgroup |
O Android 12 e versões mais recentes têm uma seção AggregateProfiles que contém perfis agregados, cada um deles é um alias para um conjunto de um ou mais perfis. As definições de perfil agregado consistem em:
- O campo Nome especifica o nome do perfil agregado.
- O campo Perfis lista os nomes dos perfis incluídos no perfil agregado.
Quando um perfil agregado é aplicado, todos os perfis que o contêm 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 se inclui).
Comando de linguagem task_profiles init
Um comando task_profiles
na Linguagem de inicialização do Android
está disponível para o Android 12 e versões mais recentes para facilitar
a ativação do perfil de tarefas para um processo específico. Ele substitui o comando writepid
(descontinuado no Android 12) que era usado para migrar um
processo entre cgroups. O comando task_profiles
oferece flexibilidade para
mudar as implementações subjacentes sem afetar as camadas superiores. No
exemplo abaixo, esses dois comandos executam a mesma operação:
writepid /dev/cpuctl/top-app/tasks
Descontinuado no Android 12, esse recurso era usado para gravar o PID da tarefa atual no arquivo
/dev/cpuctl/top-app/tasks
.task_profiles MaxPerformance
Une o processo atual ao grupo de apps principais 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 versões mais recentes. Ele aceita um ou mais parâmetros, representando os
nomes dos perfis especificados no arquivo task_profiles.json
.
Por perfis de tarefas no nível da API
No Android 12 e versões mais recentes, é possível modificar ou substituir
definições nos arquivos cgroups.json
e task_profiles.json
padrão,
baseando a mudança no nível da API do Android ou na partição
do fornecedor.
Para substituir as definições com base no nível da API, os seguintes arquivos precisam estar presentes no dispositivo:
/system/etc/task_profiles/cgroups_<API level>.json
Use isso para grupos de controle específicos de um nível de API.
/system/etc/task_profiles/task_profiles_<API level>.json
Use isso para perfis específicos de um nível da API.
Para substituir as definições da partição do fornecedor, os seguintes arquivos precisam 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 (no nível da API ou do fornecedor) vai substituir a definição anterior. 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:
- Arquivos
cgroups.json
etask_profiles.json
padrão. - Arquivos específicos do nível da API, se presentes.
- Arquivos de partição do fornecedor, se presentes.
Mudanças na API
O Android 10 e versões mais recentes mantêm as funções set_cpuset_policy
,
set_sched_policy
e get_sched_policy
sem mudanças 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 a quebra
do código atual, verifique se o novo código inclui um novo cabeçalho
processgroup/sched_policy.h
.
Os módulos que usam qualquer uma dessas funções precisam adicionar dependência à
biblioteca libprocessgroup
no makefile. Se um módulo não usar nenhuma outra
funcionalidade libcutils
, exclua 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:
Tipo | API e definição |
---|---|
bool |
SetTaskProfiles(int tid, const std::vector
Aplica os perfis de tarefa especificados em profiles à linha de execução especificada por
um ID de linha de execução (tid, na sigla em inglês) usando o parâmetro tid . |
bool |
SetProcessProfiles(uid_t uid, pid_t pid, const std::vector
Aplica os perfis de tarefas especificados em profiles ao processo especificado
pelos IDs de usuário e processo usando os parâmetros uid e pid |
bool |
CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
Retorna se um controlador de cgroup especificado por cgroup_name existe.
Se true , define a variável path como a raiz desse cgroup |
bool |
CgroupGetAttributePath(const std::string& attr_name, std::string* path)
Retorna se um atributo de perfil especificado por attr_name existe. Se
true , define a variável path como o caminho do arquivo associado a
esse atributo de perfil. |
bool |
CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)
Retorna se um atributo de perfil especificado por attr_name existe. Se
true , define a variável path como o caminho do arquivo associado a
esse atributo de perfil e à linha de execução especificada pelo ID da linha de execução usando
o parâmetro tid . |
bool |
UsePerAppMemcg()
Retorna se o sistema está configurado para usar cgroups de memória por app. |