В Android 10 и более поздних версиях используется уровень абстракции контрольной группы (cgroup) с профилями задач, которые разработчики могут использовать для описания набора (или наборов) ограничений, применяемых к потоку или процессу. Затем система следует предписанным действиям профилей задач, чтобы выбрать одну или несколько подходящих cgroup, через которые применяются ограничения, а изменения в базовый набор функций cgroup могут быть внесены без влияния на более высокие уровни программного обеспечения.
О cgroups
Cgroups предоставляют механизм агрегации и разделения наборов задач (состоящих из процессов, потоков и всех их будущих дочерних элементов) на иерархические группы со специализированным поведением. Android использует cgroups для управления и учёта системных ресурсов, таких как использование и распределение ресурсов ЦП и памяти, с поддержкой cgroups ядра Linux v1 и cgroups v2 .
Android 9 и ниже
В Android 9 и более ранних версиях скрипт инициализации init.rc
содержал набор доступных cgroups, их точек монтирования и версий. Хотя эти данные можно было изменить, фреймворк Android ожидал наличия определённого набора cgroups в определённых местах с определённой версией и иерархией подгрупп, основанной на скрипте. Это ограничивало возможность выбора следующей версии cgroup для использования или изменения иерархии cgroups для использования новых функций.
Android 10 и выше
Android 10 и выше используют cgroups с профилями задач:
- Настройка cgroup. Разработчики описывают настройку cgroups в файле
cgroups.json
, чтобы определить наборы cgroups, а также места их монтирования и атрибуты. Все cgroups монтируются на раннем этапе инициализации. - Профили задач. Они предоставляют абстракцию, которая отделяет требуемую функциональность от деталей её реализации. Фреймворк Android применяет профили задач, как описано в файле
task_profiles.json
, к процессу или потоку, используя APISetTaskProfiles
иSetProcessProfiles
. (Эти API доступны только в Android 11 и более поздних версиях.)
Для обеспечения обратной совместимости устаревшие функции set_cpuset_policy
, set_sched_policy
и get_sched_policy
предоставляют тот же API и функционал, но их реализация была изменена для использования профилей задач. Для новых сценариев использования AOSP рекомендует использовать новые API профилей задач вместо устаревшей функции set_sched_policy
.
Файл описания Cgroups
Контроллеры Cgroups описаны в файле cgroups.json
, расположенном в папке <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
. Каждый контроллер описан в подразделе и должен иметь как минимум следующее:
- Имя, определяемое полем Контроллер .
- Путь монтирования, определяемый полем Путь .
- Mode , UID (идентификатор пользователя) и GID (идентификатор группы), описывающие владельца и режимы доступа для файлов по этому пути (все необязательно).
- Необязательный атрибут, имеющий значение true , чтобы разрешить системе игнорировать ошибку монтирования, вызванную контроллером cgroup, монтирование которого ядро не поддерживает.
Пример файла cgroups.json
В примере ниже показаны описания контроллеров cgroup v1 ( Cgroups
) и cgroup v2 ( Cgroups2
) с соответствующими им путями.
{
"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"
}
]
}
}
Этот пример файла содержит два раздела: Cgroups (с описанием контроллеров cgroup v1) и Cgroups2 (с описанием контроллеров cgroup v2). Все контроллеры в иерархии cgroups v2 монтируются в одном месте. Поэтому раздел Cgroups2 имеет собственные атрибуты Path , Mode , UID и GID , описывающие расположение и атрибуты корня иерархии. Атрибут Path для контроллеров в Cgroups2 задаётся относительно этого корневого пути. В Android 12 и более поздних версиях можно определить контроллер cgroup, указанный с параметрами path и mode, как "Optional"
, установив его в true
.
Файл cgroups.json
анализируется в процессе инициализации на ранней стадии, и группы cgroups монтируются в указанных местах. Чтобы получить места монтирования групп cgroups позже, используйте API-функцию CgroupGetControllerPath
.
Файл профилей задач
Файл task_profiles.json
находится в папке <ANDROID_BUILD_TOP>/system/core/libprocessgroup/profiles/
. Он используется для описания определённого набора действий, применяемых к процессу или потоку. Набор действий связан с именем профиля, которое используется в вызовах SetTaskProfiles
и SetProcessProfiles
для вызова действий профиля.
Пример файла 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" ]
}
}
Назначьте имена конкретным файлам cgroup в качестве записей в списке «Атрибуты» . Каждая запись содержит следующее:
- Поле Имя указывает имя атрибута.
- Поле Controller ссылается на контроллер cgroup из файла
cgroups.json
по его имени. - Поле Файл именует конкретный файл в этом контроллере.
Атрибуты — это ссылки в определениях профилей задач. За пределами профилей задач используйте их только в тех случаях, когда фреймворку требуется прямой доступ к этим файлам, и этот доступ невозможно абстрагировать с помощью профилей задач. Во всех остальных случаях используйте профили задач; они обеспечивают лучшее разделение между требуемым поведением и деталями его реализации.
Раздел «Профили» содержит определения профилей задач со следующим:
- Поле Имя определяет имя профиля.
В разделе «Действия» перечислен набор действий, выполняемых при применении профиля. Каждое действие включает в себя следующее:
- Поле «Имя» определяет действие.
- Раздел Params определяет набор параметров для действия.
Поддерживаемые действия перечислены в таблице:
Действие | Параметр | Описание |
---|---|---|
SetTimerSlack | Slack | Таймер запаздывания в нс |
SetAttribute | Name | Имя, ссылающееся на атрибут из раздела «Атрибуты». | Value | Значение, которое должно быть записано в файл, представленное именованным атрибутом |
WriteFile | FilePath | путь к файлу | Value | значение для записи в файл |
JoinCgroup | Controller | Имя контроллера cgroup из cgroups.json |
Path | Путь подгруппы в иерархии контроллера cgroup |
В Android 12 и более поздних версиях есть раздел AggregateProfiles , содержащий агрегированные профили, каждый из которых является псевдонимом для набора из одного или нескольких профилей. Определения агрегированных профилей включают в себя следующее:
- Поле «Имя» указывает имя совокупного профиля.
- В поле «Профили» перечислены названия профилей, включенных в совокупный профиль.
При применении агрегированного профиля автоматически применяются все содержащие его профили. Агрегатные профили могут содержать как отдельные профили, так и другие агрегированные профили, при условии отсутствия рекурсий (профилей, включающих в себя самих).
команда языка инициализации task_profiles
Команда task_profiles
в языке Android Init Language доступна для Android 12 и более поздних версий, упрощая активацию профиля задачи для конкретного процесса. Она заменяет команду writepid
(устарела в Android 12), которая использовалась для миграции процесса между контрольными группами. Команда task_profiles
обеспечивает гибкость для изменения базовых реализаций без влияния на верхние уровни. В примере ниже эти две команды фактически выполняют одну и ту же операцию:
writepid /dev/cpuctl/top-app/tasks
Устарело в Android 12. Использовалось для записи PID текущей задачи в файл
/dev/cpuctl/top-app/tasks
.task_profiles MaxPerformance
Присоединяет текущий процесс к группе top-app под контроллером «cpu» (
cpuctl
), что приводит к записи PID процесса вdev/cpuctl/top-app/tasks
.
Для миграции задач в иерархиях cgroup в Android 12 и более поздних версиях всегда используйте команду task_profiles
. Она принимает один или несколько параметров, представляющих имена профилей, указанных в файле task_profiles.json
.
Профили задач на уровне API
В Android 12 и более поздних версиях вы можете изменять или переопределять определения в файлах cgroups.json
и task_profiles.json
по умолчанию, либо основывая изменения на уровне API Android, либо выполняя их из раздела поставщика.
Для переопределения определений на основе уровня API на устройстве должны присутствовать следующие файлы:
/system/etc/task_profiles/cgroups_<API level>.json
Используйте это для контрольных групп, специфичных для определенного уровня API.
/system/etc/task_profiles/task_profiles_<API level>.json
Используйте это для профилей, специфичных для уровня API.
Для переопределения определений из раздела поставщика на устройстве должны присутствовать следующие файлы:
-
/vendor/etc/cgroups.json
-
/vendor/etc/task_profiles.json
Если определение атрибута или профиля в этих файлах использует то же имя, что и в файле по умолчанию, определение файла (уровня API или уровня поставщика) переопределяет предыдущее определение. Обратите внимание также, что определения уровня поставщика переопределяют определения уровня API. Если новое определение имеет новое имя, то набор атрибутов или профилей изменяется в соответствии с новым определением.
Система Android загружает файлы cgroup
и task_profile
в следующем порядке:
- Файлы
cgroups.json
иtask_profiles.json
по умолчанию. - Файлы, специфичные для уровня API, если таковые имеются.
- Файлы разделов поставщика, если они есть.
Изменения в существующем API
В Android 10 и более поздних версиях функции set_cpuset_policy
, set_sched_policy
и get_sched_policy
сохраняются без изменений в API. Однако в Android 10 эти функции перемещены в libprocessgroup
, которая теперь содержит всю функциональность, связанную с cgroup.
Хотя заголовок cutils/sched_policy.h
все еще существует, чтобы избежать нарушения существующего кода, убедитесь, что новый код включает новый заголовок processgroup/sched_policy.h
.
Модули, использующие любую из этих функций, должны добавить зависимость от библиотеки libprocessgroup
в свой make-файл. Если модуль не использует другие функции libcutils
, удалите зависимость от библиотеки libcutils
из make-файла.
API-интерфейсы профилей задач
Частные API в processgroup/processgroup.h
определены в таблице:
Тип | API и определение |
---|---|
bool | SetTaskProfiles(int tid, const std::vector Применяет профили задач, указанные в profiles к потоку, указанному идентификатором потока (tid), используя его параметр tid . |
bool | SetProcessProfiles(uid_t uid, pid_t pid, const std::vector Применяет профили задач, указанные в profiles к процессу, указанному его пользователем, и идентификаторы процесса, используя параметры uid и pid |
bool | CgroupGetControllerPath(const std::string& cgroup_name, std::string* path) Возвращает, существует ли контроллер cgroup, заданный параметром cgroup_name ; если true , устанавливает переменную path в корень этой cgroup |
bool | CgroupGetAttributePath(const std::string& attr_name, std::string* path) Возвращает, существует ли атрибут профиля, заданный attr_name ; если true , устанавливает переменную path на путь к файлу, связанному с этим атрибутом профиля. |
bool | CgroupGetAttributePathForTask(const std::string& attr_name, int tid, std::string* path) Возвращает, существует ли атрибут профиля, заданный параметром attr_name ; если true , устанавливает переменную path на путь к файлу, связанному с этим атрибутом профиля, и на поток, заданный его идентификатором потока с помощью параметра tid . |
bool | UsePerAppMemcg() Возвращает информацию о том, настроена ли система на использование контрольных групп памяти для каждого приложения. |