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 de restricciones para aplicar a un subproceso o proceso. Luego, el sistema sigue las acciones prescritas de los perfiles de tareas para seleccionar uno o más grupos de control de grupos adecuados, a través de los cuales se aplican restricciones, y se pueden realizar cambios en el conjunto de funciones subyacentes del grupo de control de grupos sin afectar las capas de software superiores.
Información acerca de cgroups
Los grupos de control proporcionan un mecanismo para agregar y particionar conjuntos de tareas (que consisten en procesos, subprocesos y todos sus elementos secundarios futuros) en grupos jerárquicos con comportamiento especializado. Android usa cgroups para controlar y contabilizar los recursos del sistema, como el uso y la asignación de CPU y memoria, con compatibilidad con los 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 activación 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 cgroup con perfiles de tareas:
- Configuración de cgroups. Los desarrolladores describen la configuración de cgroups en su archivo
cgroups.json
para definir conjuntos de cgroups, sus ubicaciones de activación y sus atributos. Todos los cgroups se activan durante la etapa de inicio inicial del proceso de inicialización. - Perfiles de tareas. Estos proporcionan una abstracción que separa 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 casos de uso nuevos, AOSP recomienda usar las nuevas APIs de perfiles de tareas en lugar de la función set_sched_policy
heredada.
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 un mínimo de lo siguiente:
- Nombre, definido por el campo Controller.
- Es la ruta de activación, definida por el campo Path.
- Modo, UID (ID de usuario) y GID (ID de grupo) que describen el propietario y los modos de acceso de los archivos de esta ruta de acceso (todos opcionales).
- Opcional, configurado como true para permitir que el sistema ignore el error de activación causado por un controlador de cgroup que el kernel no admite ser activado.
Ejemplo de archivo cgroups.json
En el siguiente ejemplo, se muestran descripciones para los controladores 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 Controladores 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"
si lo estableces en true
.
El archivo cgroups.json
se analiza como parte del proceso de init, durante la etapa de inicio anticipado, y los cgroups se activan en las ubicaciones especificadas. Para obtener más adelante las ubicaciones de activación de cgroup, usa la función de la API de 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 con 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 cgroup específicos como entradas en la lista Atributos. Cada entrada contiene lo siguiente:
- 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 Archivo asigna un nombre a un archivo específico en este controlador.
Los atributos son referencias en las definiciones de perfiles de tareas. Fuera de los perfiles de tareas, úsalo 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 una mejor desvinculación entre el comportamiento requerido y sus detalles de implementación.
La sección Profiles contiene definiciones de perfiles de tareas con lo siguiente:
- El campo Name define el nombre del perfil.
En la sección Actions, se muestra un conjunto de 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 tabla:
Acción | Parámetro | Descripción |
---|---|---|
SetTimerSlack |
Slack |
Tiempo de inactividad del temporizador en ns |
SetAttribute |
Name |
Un nombre que hace referencia a un atributo de la sección Atributos |
Value |
Un valor que se escribirá en el archivo representado por el atributo nombrado | |
WriteFile | FilePath | ruta de acceso al archivo |
Value | un valor que se escribirá en el archivo | |
JoinCgroup |
Controller |
Un nombre del controlador de cgroup de cgroups.json |
Path |
Es una ruta de acceso de 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 perfiles agregados constan de lo siguiente:
- El campo Nombre especifica el nombre del perfil agregado.
- En el campo Perfiles, se muestran 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 lo contienen. Los perfiles agregados pueden contener perfiles individuales o bien otros perfiles agregados, siempre y cuando no haya recursión (un perfil que se incluye a sí mismo).
Comando de lenguaje de inicialización de task_profiles
Hay un comando task_profiles
en el lenguaje de inicialización de Android 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 usó 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 efectiva:
writepid /dev/cpuctl/top-app/tasks
Dejó de estar disponible en Android 12, se usó para escribir el PID de la tarea actual en el archivo
/dev/cpuctl/top-app/tasks
.task_profiles MaxPerformance
Une el proceso actual en el grupo de la app principal en el controlador "cpu" (
cpuctl
), lo que genera la escritura del PID del proceso endev/cpuctl/top-app/tasks
.
Usa siempre 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 definiciones en los archivos cgroups.json
y task_profiles.json
predeterminados. Para ello, debes basar tu cambio en el nivel de API de Android o hacerlo 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 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 usan el mismo nombre que el del 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 predeterminados
cgroups.json
ytask_profiles.json
. - 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 traslada estas funciones a libprocessgroup
, que ahora contiene todas las funciones relacionadas con cgroup.
Si bien el encabezado cutils/sched_policy.h
aún existe, para evitar romper 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 una dependencia en la biblioteca libprocessgroup
a su archivo makefile. Si un módulo no usa ninguna otra funcionalidad de libcutils
, quita la dependencia de la biblioteca libcutils
del archivo makefile.
APIs de perfiles de tareas
Las APIs privadas en processgroup/processgroup.h
se definen en la 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 que especifican
los 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 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 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. |