Capa de abstracción de Cgroup

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 para aplicar a un hilo o un 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 funciones de cgroup subyacente sin afectar las capas de software superiores.

Acerca de cgroups

Los Cgroups proporcionan un mecanismo para agregar y particionar conjuntos de tareas (que consisten en procesos, subprocesos y todos sus hijos futuros) en grupos jerárquicos con comportamiento especializado. Android usa cgroups para controlar y dar cuenta de los recursos del sistema, como el uso y la asignación de CPU y memoria, con soporte para kernel de Linux cgroups v1 y cgroups v2 .

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 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 para usar o cambiar la jerarquía de cgroup para usar nuevas funciones.

Android 10 y superior

Android 10 y superior 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 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 brindar compatibilidad con versiones anteriores, las funciones heredadas set_cpuset_policy , set_sched_policy y get_sched_policy brindan la misma API y funcionalidad, pero su implementación se modificó para usar perfiles de tareas. Para nuevos casos de uso, AOSP recomienda usar nuevas API 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 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 para los archivos en esta ruta (todo opcional).
  • Atributo opcional , establecido en verdadero para permitir que el sistema ignore el error de montaje causado por un controlador cgroup que el kernel no admite que se monte.

Ejemplo de archivo cgroups.json

El siguiente ejemplo muestra descripciones para 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 en la jerarquía de 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 Path para Controllers en Cgroups2 es relativo a esa ruta raíz. En Android 12 y versiones posteriores, puede 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 inicial de inicio, y los cgroups se montan en las ubicaciones especificadas. Para obtener más tarde 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 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 de 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 puede 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 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 Holgura 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 al archivo
Value un valor para ser escrito 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 de 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 recurrencias (un perfil que se incluya a sí mismo).

task_profiles comando de idioma de inicio

Un comando task_profiles en Android Init Language 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 usó para migrar un proceso entre cgroups. El comando task_profiles brinda flexibilidad para cambiar las implementaciones subyacentes sin afectar 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 usaba para escribir el PID de la tarea actual en el /dev/cpuctl/top-app/tasks .

  • task_profiles MaxPerformance

    Une el proceso actual al grupo de aplicaciones principales bajo el controlador "cpu" ( cpuctl ), lo que resulta en 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 .

Perfiles de tareas por nivel de API

En Android 12 y versiones posteriores, puede modificar o anular definiciones en los archivos cgroups.json y task_profiles.json predeterminados, ya sea basando su cambio en el nivel de la 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

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

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

    Utilícelo 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 de nivel de proveedor anulan las definiciones de nivel de API. Si la nueva definición tiene un nuevo nombre, 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. 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 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 processgroup/sched_policy.h en su lugar.

Los módulos que usan cualquiera de estas funciones deben agregar la dependencia de la biblioteca libprocessgroup en su archivo MAKE. Si un módulo no usa ninguna otra funcionalidad de 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:

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

Aplica los perfiles de tareas especificados en los 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 los profiles al proceso especificado por su usuario y los ID de proceso mediante 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 de 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 de 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 de path en la ruta del archivo asociado con ese atributo de perfil y en el subproceso especificado por su ID de subproceso mediante el parámetro tid .

bool UsePerAppMemcg()

Devuelve si el sistema está configurado para usar cgroups de memoria por aplicación.