Capa de abstracción de Cgroup

Android 10 y versiones posteriores utilizan 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 para aplicar a un hilo o proceso. Luego, el sistema sigue las acciones prescritas de los perfiles de tareas para seleccionar uno o más cgroups apropiados, a través de los cuales se aplican restricciones y se pueden realizar cambios en el conjunto de características subyacentes del cgroup sin afectar las capas superiores de software.

Acerca de los grupos c

Los Cgroups proporcionan un mecanismo para agregar y dividir conjuntos de tareas (que constan de procesos, subprocesos y todos sus futuros hijos) 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 soporte para cgroups v1 y cgroups v2 del kernel de Linux.

Android 9 y anteriores

En Android 9 y versiones anteriores, el script de inicialización init.rc contenía el conjunto de cgroups disponibles, sus puntos de montaje y versiones. Si bien estos podrían cambiarse, el marco de trabajo de Android esperaba que existiera un conjunto específico de cgroups en ubicaciones específicas con una versión específica y una jerarquía de subgrupos, según el script. Esto limitó la capacidad de elegir la siguiente versión de cgroup a usar o de cambiar la jerarquía de cgroup para usar nuevas funciones.

Android 10 y superior

Android 10 y versiones posteriores utilizan 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 y sus ubicaciones y atributos de montaje. Todos los cgroups se montan durante la etapa inicial 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 marco de trabajo de Android aplica los perfiles de tareas como se describe en el archivo task_profiles.json a un proceso o subproceso mediante las API SetTaskProfiles y SetProcessProfiles . (Estas API son exclusivas de Android 11 y versiones posteriores).

Para proporcionar compatibilidad con versiones anteriores, las funciones heredadas set_cpuset_policy , set_sched_policy y get_sched_policy proporcionan la misma API y funcionalidad, pero su implementación se ha modificado para utilizar perfiles de tareas. Para nuevos casos de uso, AOSP recomienda utilizar nuevas API de perfiles de tareas en lugar de la función heredada set_sched_policy .

Archivo de descripción de grupos C

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 Controlador .
  • Ruta de montaje, definida por el campo Ruta .
  • Modo , UID (ID de usuario) y GID (ID de grupo) que describen el propietario y los modos de acceso a los archivos en esta ruta (todos opcionales).
  • Atributo opcional , establecido en verdadero para permitir que el sistema ignore el error de montaje causado por un controlador cgroup cuyo montaje el kernel no admite.

Ejemplo de archivo cgroups.json

El siguiente ejemplo muestra descripciones de los controladores cgroup v1 ( Cgroups ) y cgroup v2 ( Cgroups2 ) con sus respectivas rutas.

{
  "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 cgroup v1) y Cgroups2 (que describe los controladores cgroup v2). Todos los controladores de la jerarquía cgroups v2 están montados 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 Ruta para controladores en Cgroups2 es relativo a esa ruta raíz. En Android 12 y versiones posteriores, puedes definir un controlador cgroup que se especifica con la ruta y el modo como "Optional" configurándolo en true .

El archivo cgroups.json se analiza como parte del proceso de inicio, durante la etapa de inicio inicial, y los cgroups se montan en las ubicaciones especificadas. Para obtener posteriormente las ubicaciones de montaje de cgroup, utilice la función API CgroupGetControllerPath .

Archivo de perfiles de tareas

El archivo task_profiles.json se encuentra en <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/ . Úselo para describir un conjunto específico de acciones que se aplicarán a un proceso o hilo. Un conjunto de acciones está asociado con un nombre de perfil, que se utiliza 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" ]
     }
}

Asigne nombres a archivos cgroup específicos como entradas en su lista de Atributos . Cada entrada contiene lo siguiente:

  • Campo de nombre : especifica el nombre del atributo.
  • Campo Controlador : hace referencia a un controlador cgroup del archivo cgroups.json , por su nombre.
  • Campo de archivo : nombra un archivo específico bajo este controlador.

Los atributos son referencias en las definiciones de perfiles de tareas. Fuera de los perfiles de tareas, utilícelos solo cuando el marco requiera acceso directo a esos archivos y el acceso no se pueda abstraer mediante perfiles de tareas. En todos los demás casos, utilice perfiles de tareas; 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:

  • Campo de nombre : define el nombre del perfil.
  • Sección de acciones : enumera un conjunto de acciones realizadas cuando se aplica el perfil. Cada acción tiene lo siguiente:

    • Campo de nombre que especifica la acción.
    • Sección de parámetros que 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 Temporizador flojo 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 al archivo
Value un valor que se escribirá en el archivo
JoinCgroup Controller Un nombre del controlador cgroup de cgroups.json
Path Una ruta de subgrupo en la jerarquía del controlador cgroup

Android 12 y versiones posteriores cuentan con 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:

  • Campo de nombre : especifica el nombre del perfil agregado.
  • Campo Perfiles : enumera los nombres de los perfiles incluidos en el perfil agregado.

Cuando se aplica un perfil agregado, todos los perfiles que lo contienen también se aplican automáticamente. Los perfiles agregados pueden contener tanto perfiles individuales como otros perfiles agregados, siempre que no haya recursividades (un perfil que se incluye a sí mismo).

comando de idioma de inicio task_profiles

Un comando task_profiles en el lenguaje de inicio de Android está disponible para Android 12 y versiones posteriores para facilitar la activación del perfil de tarea 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 ningún efecto en las capas superiores. En el siguiente ejemplo, estos dos comandos realizan efectivamente la misma operación:

  • writepid /dev/cpuctl/top-app/tasks

    Obsoleto 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 al grupo de aplicaciones principales bajo el controlador "cpu" ( cpuctl ), lo que da como resultado escribir el PID del proceso en dev/cpuctl/top-app/tasks .

Utilice 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 .

Por perfiles de tarea a nivel de API

En Android 12 y versiones posteriores, puede modificar o anular las definiciones en los archivos cgroups.json y task_profiles.json predeterminados, ya sea basando el cambio en el nivel de API de Android o haciéndolo desde la partición del proveedor.

Para anular las definiciones basadas en el nivel de API, los siguientes archivos deben estar presentes en el dispositivo:

  • pro/system/etc/task_profiles/cgroups_<API level>.json

    Utilice esto para cgroups específicos de un nivel de API.

  • /system/etc/task_profiles/task_profiles_<API level>.json

    Utilice esto 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 usa el mismo nombre que en el archivo predeterminado, la definición del archivo (nivel de API o nivel de proveedor) anula la definición anterior. Tenga en cuenta también que las definiciones a nivel de proveedor anulan las definiciones a nivel de API. Si la nueva definición tiene un nuevo nombre, entonces 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:

  1. Archivos cgroups.json y task_profiles.json predeterminados.
  2. Archivos específicos del nivel de API, si están presentes.
  3. Archivos de partición del proveedor, si están presentes.

Cambios en la API existente

Android 10 y versiones posteriores mantienen 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.

Aunque el encabezado cutils/sched_policy.h todavía existe, para evitar romper el código existente, asegúrese de que el nuevo código incluya un nuevo encabezado processgroup/sched_policy.h .

Los módulos que utilizan cualquiera de estas funciones deben agregar dependencia de la biblioteca libprocessgroup en su archivo MAKE. Si un módulo no utiliza ninguna otra funcionalidad libcutils , elimine la dependencia de la biblioteca libcutils del archivo MAKE.

API de perfiles de tareas

Las API privadas en processgroup/processgroup.h se definen en la siguiente tabla:

Tipo API y definición
bool SetTaskProfiles(int tid, const std::vector & profiles) SetTaskProfiles(int tid, const std::vector & profiles)

Aplica los perfiles de tarea especificados en profiles al subproceso especificado por un ID de subproceso (tid) utilizando su parámetro tid .

bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles) SetProcessProfiles(uid_t uid, pid_t pid, const std::vector & profiles)

Aplica los perfiles de tarea especificados en profiles al proceso especificado por su usuario y sus ID de proceso utilizando los parámetros uid y pid .

bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path)

Devuelve si existe un controlador 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 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 del archivo asociado con ese atributo de perfil y en el hilo especificado por su ID de hilo usando el parámetro tid .

bool UsePerAppMemcg()

Devuelve si el sistema está configurado para utilizar grupos de memoria por aplicación.