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 adequados, pelos quais as restrições são aplicadas. As mudanças no conjunto de recursos do cgroup podem ser feitas sem afetar as camadas de software mais altas.
Sobre os cgroups
Os cgroups oferecem um mecanismo para agregar e particionar conjuntos de tarefas (que consistem em processos, linhas de execução e todos os futuros filhos) em grupos hierárquicos com comportamento especializado. O Android usa cgroups para controlar e considerar recursos do sistema, como uso e alocação de CPU e memória, com suporte ao kernel do Linux cgroups v1 e cgroups v2.
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 eles pudessem
ser alterados, 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 de alterar 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 do Cgroup. Os desenvolvedores descrevem a configuração dos cgroups no arquivo
cgroups.json
para definir conjuntos de cgroups e os locais e atributos 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 deve ter pelo menos os seguintes itens:
- 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 dos 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 de inicialização
inicial, 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 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 Atributos. Cada entrada contém o seguinte:
- O campo Nome especifica o nome do atributo.
- O campo Controller faz referência a um controlador cgroup do arquivo
cgroups.json
pelo próprio 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 abstraído 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 inclua a si mesmo).
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, sem afetar as camadas superiores. No exemplo abaixo, esses dois comandos executam efetivamente 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 do app superior sob o 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, que representam 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 mudar ou substituir
as definições nos arquivos padrão cgroups.json
e task_profiles.json
,
baseando a mudança no nível da API do Android ou usando a 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 para cgroups específicos de um nível da 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 de nível da API, se houver.
- 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 a dependência da
biblioteca libprocessgroup
ao makefile. Se um módulo não usar nenhuma outra
funcionalidade libcutils
, elimine a dependência da biblioteca
libcutils
do makefile.
APIs de perfis de tarefas
As APIs particulares em processgroup/processgroup.h
estã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) usando o parâmetro tid . |
bool |
SetProcessProfiles(uid_t uid, pid_t pid, const std::vector
Aplica os perfis de tarefa especificados em profiles ao processo especificado
pelos IDs de usuário e de 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. |