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, em que as restrições são aplicadas, e as mudanças no conjunto de recursos do cgroup subjacente podem ser feitas sem afetar as camadas de software mais altas.
Sobre cgroups
Os cgroups fornecem um mecanismo para agregar e particionar conjuntos de tarefas (que consistem em processos, linhas de execução e todos os filhos futuros deles) 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 eles pudessem ser mudados, o framework do Android esperava que um conjunto específico de cgroups existisse em locais específicos com uma versão e uma hierarquia de subgrupos específicas, com base no script. Isso limitava a capacidade de escolher a próxima versão do cgroup a ser usada ou de 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 do cgroup. Os desenvolvedores descrevem a configuração dos cgroups no arquivo
cgroups.json
para definir conjuntos de cgroups, além dos locais e atributos de montagem. Todos os cgroups são montados durante o estágio de inicialização antecipada 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 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 legadas set_cpuset_policy
, set_sched_policy
e get_sched_policy
fornecem 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 as novas APIs de perfis de tarefas em vez da função legada set_sched_policy
.
Arquivo de descrição dos 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 precisa ter, no mínimo, o seguinte:
- Nome, definido pelo campo Controlador.
- Caminho de montagem, definido pelo campo Caminho.
- Modo, 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 cgroup que o kernel não aceita ser montado.
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 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
cgroup especificado com caminho e modo como "Optional"
ao definir como true
.
O arquivo cgroups.json
é analisado como parte do processo de inicialização, durante a fase de
inicialização antecipada, e os cgroups são montados nos locais especificados. Para obter 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
thread. 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 Controlador faz referência a um controlador de cgroup do arquivo
cgroups.json
pelo nome. - O campo Arquivo nomeia um arquivo específico nesse controlador.
Os atributos são referências nas definições de perfil de tarefa. Fora dos perfis de tarefa, use-os somente quando o framework 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 tarefas. Eles oferecem um desacoplamento melhor entre o comportamento necessário e os detalhes da implementação.
A seção Perfis contém definições de perfil de tarefa com o seguinte:
- O campo Nome 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 |
Timer slack 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 versões mais recentes têm uma seção AggregateProfiles que contém perfis agregados, cada um deles sendo um alias para um conjunto de um ou mais perfis. As definições de perfil agregadas consistem no seguinte:
- 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 task_profiles init language
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 tarefa para um processo específico. Ele substitui o comando writepid
(descontinuado no Android 12) 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. Era usado para gravar o PID da tarefa atual no arquivo
/dev/cpuctl/top-app/tasks
.task_profiles MaxPerformance
Adiciona 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
.
Perfis de tarefas por nível de API
No Android 12 e versões mais recentes, é possível alterar ou substituir
definições nos arquivos cgroups.json
e task_profiles.json
padrão, seja
baseando a mudança no nível da API do Android ou fazendo isso 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 cgroups 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 de 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 do 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 padrão
cgroups.json
etask_profiles.json
. - Arquivos específicos do nível da API, se houver.
- Arquivos de partição do fornecedor, se houver.
Mudanças na API atual
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
, remova a dependência da biblioteca libcutils
do makefile.
APIs de perfis de tarefas
As APIs particulares 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) 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 dela usando
o parâmetro tid . |
bool |
UsePerAppMemcg()
Retorna se o sistema está configurado para usar cgroups de memória por app. |