Android 10 y versiones posteriores usan una capa de abstracción de grupo de control (cgroup) con perfiles de tareas, que los desarrolladores pueden usar para describir un conjunto (o conjuntos) de restricciones que se aplicarán a un subproceso o proceso. Luego, el sistema sigue las acciones prescritas de los perfiles de tareas para seleccionar uno o más cgroups adecuados, a través de los cuales se aplican las restricciones y se pueden realizar cambios en el conjunto de funciones de cgroup subyacente sin afectar las capas de software superiores.
Acerca de los cgroups
Los cgroups proporcionan un mecanismo para agregar y particionar conjuntos de tareas (que constan de procesos, subprocesos y todos sus futuros elementos secundarios) en grupos jerárquicos con un comportamiento especializado. Android usa cgroups para controlar y registrar los recursos del sistema, como el uso y la asignación de CPU y memoria, con compatibilidad para cgroups v1 y cgroups v2 del kernel de Linux.
Android 9 y versiones anteriores
En Android 9 y versiones anteriores, la secuencia de comandos de inicialización init.rc
contenía el conjunto de cgroups disponibles, sus puntos de montaje y sus versiones. Si bien se podían cambiar, el framework de Android esperaba que existiera un conjunto específico de cgroups en ubicaciones específicas con una versión y una jerarquía de subgrupos específicas, según la secuencia de comandos. Esto limitaba la capacidad de elegir la siguiente versión de cgroup que se usaría o de cambiar la jerarquía de cgroup para usar funciones nuevas.
Android 10 y versiones posteriores
Android 10 y versiones posteriores usan cgroups con perfiles de tareas:
- Configuración de cgroup. Los desarrolladores describen la configuración de cgroups en su archivo
cgroups.json
para definir conjuntos de cgroups, sus ubicaciones de montaje y sus atributos. Todos los cgroups se activan durante la etapa de early-init del proceso de inicialización. - Perfiles de tareas: Proporcionan una abstracción que desacopla la funcionalidad requerida de los detalles de su implementación. El framework de Android aplica los perfiles de tareas como se describe en el archivo
task_profiles.json
a un proceso o subproceso con las APIs deSetTaskProfiles
ySetProcessProfiles
. (Estas APIs son exclusivas de Android 11 y versiones posteriores).
Para proporcionar retrocompatibilidad, las funciones heredadas set_cpuset_policy
, set_sched_policy
y get_sched_policy
proporcionan la misma API y funcionalidad, pero su implementación se modificó para usar perfiles de tareas. Para los casos de uso nuevos, AOSP recomienda usar las nuevas APIs de perfiles de tareas en lugar de la función heredada set_sched_policy
.
Archivo de descripción de cgroups
Los cgroups se describen en el archivo cgroups.json
ubicado en <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Cada controlador se describe en una subsección y debe tener, como mínimo, lo siguiente:
- Nombre, definido por el campo Controlador.
- Ruta de activación, definida por el campo Ruta de acceso.
- Modo, UID (ID de usuario) y GID (ID de grupo) que describen el propietario y los modos de acceso para los archivos en esta ruta de acceso (todos opcionales).
- Atributo opcional que se establece en true para permitir que el sistema ignore el error de activación causado por un controlador de cgroup que el kernel no admite que se active.
Ejemplo de archivo cgroups.json
En el siguiente ejemplo, se muestran las descripciones de los controladores de cgroup v1 (Cgroups
) y cgroup v2 (Cgroups2
) con sus respectivas rutas de acceso.
{
"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 archivo de ejemplo contiene dos secciones: Cgroups (que describe los controladores de cgroup v1) y Cgroups2 (que describe los controladores de cgroup v2). Todos los controladores de la jerarquía de cgroups v2 se activan en la misma ubicación.
Por lo tanto, la sección Cgroups2 tiene sus propios atributos Path, Mode, UID y GID para describir la ubicación y los atributos de la raíz de la jerarquía. El atributo Path para Controllers en Cgroups2 es relativo a esa ruta de acceso raíz. En Android 12 y versiones posteriores, puedes definir un controlador de cgroup que se especifique con la ruta de acceso y el modo como "Optional"
configurándolo en true
.
El archivo cgroups.json
se analiza como parte del proceso de inicialización, durante la etapa de inicialización temprana, y los cgroups se activan en las ubicaciones especificadas. Para obtener más adelante las ubicaciones de montaje de cgroup, usa la función de la API CgroupGetControllerPath
.
Archivo de perfiles de tareas
El archivo task_profiles.json
se encuentra en <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
.
Úsalo para describir un conjunto específico de acciones que se aplicarán a un proceso o un subproceso. Un conjunto de acciones está asociado a un nombre de perfil, que se usa en las llamadas SetTaskProfiles
y SetProcessProfiles
para invocar acciones de perfil.
Ejemplo de archivo 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" ]
}
}
Asigna nombres a archivos de cgroup específicos como entradas en tu lista de Atributos. Cada entrada contiene la siguiente información:
- El campo Name especifica el nombre del atributo.
- El campo Controller hace referencia a un controlador de cgroup del archivo
cgroups.json
por su nombre. - El campo File nombra un archivo específico en este controlador.
Los atributos son referencias en las definiciones de perfiles de tareas. Fuera de los perfiles de tareas, úsalos solo cuando el framework requiera acceso directo a esos archivos y el acceso no se pueda abstraer con perfiles de tareas. En todos los demás casos, usa perfiles de tareas, ya que proporcionan un mejor desacoplamiento entre el comportamiento requerido y sus detalles de implementación.
La sección Perfiles contiene definiciones de perfiles de tareas con lo siguiente:
- El campo Nombre define el nombre del perfil.
En la sección Actions, se muestra una lista de las acciones que se realizan cuando se aplica el perfil. Cada acción tiene lo siguiente:
- El campo Name especifica la acción.
- La sección Params especifica un conjunto de parámetros para la acción.
Las acciones admitidas se enumeran en la siguiente tabla:
Acción | Parámetro | Descripción |
---|---|---|
SetTimerSlack |
Slack |
Holgura del temporizador en ns |
SetAttribute |
Name |
Un nombre que hace referencia a un atributo de la sección Atributos |
Value |
Es un valor que se escribirá en el archivo representado por el atributo con nombre. | |
WriteFile | FilePath | Ruta de acceso al archivo |
Value | un valor que se escribirá en el archivo | |
JoinCgroup |
Controller |
Nombre de un controlador de cgroup de cgroups.json |
Path |
Ruta de un subgrupo en la jerarquía del controlador de cgroup |
Android 12 y versiones posteriores incluyen una sección AggregateProfiles que contiene perfiles agregados, cada uno de los cuales es un alias para un conjunto de uno o más perfiles. Las definiciones de perfil agregado constan de lo siguiente:
- El campo Nombre especifica el nombre del perfil agregado.
- En el campo Perfiles, se enumeran los nombres de los perfiles incluidos en el perfil agregado.
Cuando se aplica un perfil agregado, también se aplican automáticamente todos los perfiles que contiene. Los perfiles agregados pueden contener perfiles individuales o bien otros perfiles agregados, siempre y cuando no haya recursiones (un perfil que se incluye a sí mismo).
Comando task_profiles init language
Un comando task_profiles
en el lenguaje de inicialización de Android está disponible para Android 12 y versiones posteriores para facilitar la activación del perfil de tareas para un proceso específico. Reemplaza el comando writepid
(obsoleto en Android 12) que se usaba para migrar un proceso entre cgroups. El comando task_profiles
proporciona flexibilidad para cambiar las implementaciones subyacentes sin afectar las capas superiores. En el siguiente ejemplo, estos dos comandos realizan la misma operación de manera eficaz:
writepid /dev/cpuctl/top-app/tasks
Obsoleto en Android 12. Se usaba para escribir el PID de la tarea actual en el archivo
/dev/cpuctl/top-app/tasks
.task_profiles MaxPerformance
Une el proceso actual al grupo de apps en primer plano en el controlador "cpu" (
cpuctl
), lo que genera la escritura del PID del proceso endev/cpuctl/top-app/tasks
.
Siempre usa el comando task_profiles
para migrar tareas en jerarquías de cgroup en Android 12 y versiones posteriores. Acepta uno o más parámetros que representan los nombres de los perfiles especificados en el archivo task_profiles.json
.
Perfiles de tareas por nivel de API
En Android 12 y versiones posteriores, puedes modificar o anular las definiciones en los archivos cgroups.json
y task_profiles.json
predeterminados, ya sea basando tu cambio en el nivel de API de Android o haciéndolo desde la partición del proveedor.
Para anular las definiciones según el nivel de API, los siguientes archivos deben estar presentes en el dispositivo:
/system/etc/task_profiles/cgroups_<API level>.json
Úsalo para cgroups específicos de un nivel de API.
/system/etc/task_profiles/task_profiles_<API level>.json
Úsalo para los perfiles específicos de un nivel de API.
Para anular las definiciones de la partición del proveedor, los siguientes archivos deben estar presentes en el dispositivo:
/vendor/etc/cgroups.json
/vendor/etc/task_profiles.json
Si un atributo o una definición de perfil en estos archivos usa el mismo nombre que en el archivo predeterminado, la definición del archivo (a nivel de la API o del proveedor) anula la definición anterior. Ten en cuenta también que las definiciones a nivel del proveedor anulan las definiciones a nivel de la API. Si la nueva definición tiene un nombre nuevo, el conjunto de atributos o perfiles se modifica con la nueva definición.
El sistema Android carga los archivos cgroup
y task_profile
en este orden:
- Archivos
cgroups.json
ytask_profiles.json
predeterminados - Archivos específicos del nivel de API, si están presentes.
- Archivos de partición del proveedor, si están presentes.
Cambios en la API existente
Android 10 y versiones posteriores conservan las funciones set_cpuset_policy
, set_sched_policy
y get_sched_policy
sin cambios en la API.
Sin embargo, Android 10 mueve estas funciones a libprocessgroup
, que ahora contiene toda la funcionalidad relacionada con cgroup.
Si bien el encabezado cutils/sched_policy.h
aún existe, para evitar que se interrumpa el código existente, asegúrate de que el código nuevo incluya un encabezado processgroup/sched_policy.h
nuevo.
Los módulos que usan cualquiera de estas funciones deben agregar la dependencia en la biblioteca libprocessgroup
a su archivo makefile. Si un módulo no usa ninguna otra función de libcutils
, quita la dependencia de la biblioteca de libcutils
del archivo makefile.
APIs de perfiles de tareas
Las APIs privadas en processgroup/processgroup.h
se definen en la siguiente tabla:
Tipo | API y definición |
---|---|
bool |
SetTaskProfiles(int tid, const std::vector
Aplica los perfiles de tareas especificados en profiles al subproceso especificado por
un ID de subproceso (tid) con su parámetro tid . |
bool |
SetProcessProfiles(uid_t uid, pid_t pid, const std::vector
Aplica los perfiles de tareas especificados en profiles al proceso especificado
por sus IDs de usuario y proceso con los parámetros uid y pid |
bool |
CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)
Devuelve si existe un controlador de cgroup especificado por cgroup_name ;
si es true , establece la variable path en la raíz de ese cgroup |
bool |
CgroupGetAttributePath(const std::string& attr_name, std::string* path)
Devuelve un valor que indica si existe un atributo de perfil especificado por attr_name . Si es true , establece la variable path en la ruta de acceso del archivo asociado con ese atributo de perfil. |
bool |
CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path)
Devuelve un valor que indica si existe un atributo de perfil especificado por attr_name . Si es
true , establece la variable path en la ruta de acceso del archivo asociado con
ese atributo de perfil y en el subproceso especificado por su ID de subproceso con el
parámetro tid . |
bool |
UsePerAppMemcg()
Devuelve si el sistema está configurado para usar cgroups de memoria por app. |