写在前面
因为CGroup是内核中的一种机制,那么在Android Oreo及以前的版本,Android已经对CGroup进行支持,但有诸多限制。在Andorid Pie以后CGroup的使用将会更灵活。Android Pie及更高版本支持CGroup抽象层与任务配置文件搭配使用,在此基础上开发者可以对控制组中的任务进行限制和监控。
注意!接下来我们将基于Android Pie及其更高的版本进行梳理,博文中的代码参考基于最新的master分支。
一、Android CGroup描述文件
CGroup会在系统early-init阶段初始化,包括CGroupV1和CGroupV2子系统的挂载路径,权限等。关于子系统的配置都定义在cgroups.json描述文件中,cgroup的初始化就是依据cgroups.json来进行初始化。
1.1 描述文件示例
aosp/system/core/libprocessgroup/profiles/cgroups.json
1 {
2 "Cgroups": [
3 {
4 "Controller": "blkio",
5 "Path": "/dev/blkio",
6 "Mode": "0775",
7 "UID": "system",
8 "GID": "system"
9 },
10 {
11 "Controller": "cpu",
12 "Path": "/dev/cpuctl",
13 "Mode": "0755",
14 "UID": "system",
15 "GID": "system"
16 },
17 {
18 "Controller": "cpuset",
19 "Path": "/dev/cpuset",
20 "Mode": "0755",
21 "UID": "system",
22 "GID": "system"
23 },
24 {
25 "Controller": "memory",
26 "Path": "/dev/memcg",
27 "Mode": "0700",
28 "UID": "root",
29 "GID": "system",
30 "Optional": true
31 }
32 ],
33 "Cgroups2": {
34 "Path": "/sys/fs/cgroup",
35 "Mode": "0775",
36 "UID": "system",
37 "GID": "system",
38 "Controllers": [
39 {
40 "Controller": "freezer",
41 "Path": "."
42 }
43 ]
44 }
45 }
46
1.1.1 Cgroups

1.1.2 Cgroups2

1.1.3 端上路径

?
1.2 CGroup子系统描述文件语法规则
{
????????"CGroupV1":
????????[
? ????????? ? ? {
? ? ????????? ? ? ? ? ? "Controller":"控制器名称",
? ? ? ? ? ? ? ? ? ? ? ? "Path":"控制器挂载路径",
? ? ? ????????? ? ? ? ? "Mode":"访问权限",
? ? ? ? ????????? ? ? ? "UID":"用户ID",
? ? ? ? ????????? ? ? ? "GID":"用户组ID",
? ? ? ? ????????? ? ? ? "Optional":是否忽略内核不支持的控制器子系统
? ? ????????? ? },
? ? ????????? ? ......
? ? ? ? ],
????????"CGroupV2":
? ? ? ? ?{
? ? ? ? ? ? ? ? "Path":"控制器挂载路径",
? ? ? ? ? ? ? ? "Mode":"访问权限",
????????????????"UID":"用户ID",
????????????????"GID":"用户组ID",
????????????????"Controller":
? ? ? ? ? ? ? ? [
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ????????? ? ? ????????? ? ? "Controller":"控制器名称",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "Path":".",
? ? ? ????????????????? ? ? ? ? "Mode":"访问权限",
? ? ? ? ????????? ????????? ? ? "UID":"用户ID",
? ? ? ? ????????????????? ? ? ? "GID":"用户组ID"
? ? ????????? ? ????????},
? ? ? ? ? ? ? ? ? ? ? ? ......
? ? ? ? ? ? ? ? ]
? ? ? ? }
}
CGroup版本:Cgroups指cgroup v1和Cgroups2指cgroup v2。在cgroup v2中,所有的控制器子系统均挂载在同一路径下(/sys/fs/cgroup)。
控制器名称:控制器名称一般跟随内核中支持的控制器名来定义。
挂载路径:因为内核中的cgroup通过虚拟文件系统将控制节点暴露给用户空间,所以要制定控制器的挂在路径。
访问模式:也就是我们常见的访问权限。(可选)
UID:用户ID。(可选)
GID:用户组ID。(可选)
Optional:(可选)选择属性,设置为true,表示系统忽略内核不支持的cgroup子系统。这部分是由于必要的,因为有些平台释放的内核有可能会定制,或者对内核控制器子系统的支持情况也不尽相同。
二、Android CGroup配置文件
配置文件的使用是最关键的,也是大部分开发者需要花费时间对cgroup控制器进行tuning的地方。这个文件用于描述应用于进程或任务(线程)上的规则。API如SetTaskProfiles和SetProcessProfiles会根据下面配置文件中定义的规则分别用于操作任务(线程)和进程。
2.1 配置文件示例
aosp/system/core/libprocessgroup/profiles/task_profiles.json
{
"Attributes": [
{
"Name": "LowCapacityCPUs",
"Controller": "cpuset",
"File": "background/cpus"
},
......
],
"Profiles": [
{
"Name": "HighEnergySaving",
"Actions": [
{
"Name": "JoinCgroup",
"Params":
{
"Controller": "cpu",
"Path": "background"
}
}
]
},
......
],
"AggregateProfiles": [
{
"Name": "SCHED_SP_DEFAULT",
"Profiles": [ "TimerSlackNormal" ]
},
......
]
}
2.2 配置文件语法规则
2.2.1 Attributes配置语法规则
Attributes为特定的cgroup文件指定一个名称,它是Profiles中定义的引用,仅在Framework层需要直接访问相应文件,或Framework无法通过抽象层去使用Profiles时使用。在所有其他情况下,请使用任务配置文件;它们可以更好地分离所需行为及其实现详情。
? "Attributes": [ ? ? { ? ? ? "Name": "?Attribute名称", ? ? ? "Controller": "控制器名称", ? ? ? "File": "对应控制下的特定文件名" ? ? }, ? ? ......
2.2.2 Profiles配置语法规则
下面是其中一个profile段的示例:
? "Profiles": [ ? ? { ? ? ? "Name": "profile名称", ? ? ? "Actions": [ ? ? ? ? { ? ? ? ? ? "Name": "指定操作", ? ? ? ? ? "Params": ? ? ? ? ? { ? ? ? ? ? ? "Controller": "cgroup.json中的cgroup控制器名称", ? ? ? ? ? ? "Path": "group 控制器层次结构中的子控制组路径" ? ? ? ? ? } ? ? ? ? } ? ? ? ] ? ? },
2.2.3 AggregateProfiles配置语法规则
Android 12 及更高版本新增?AggregateProfiles?部分,是对Profile段的聚合,每个聚合Profile段都是一个或多个Profile段的别名。
? "AggregateProfiles": [ ? ? { ? ? ? "Name": "聚合Profile的别名", ? ? ? "Profiles": [ 所包含的所有Profile名称] ? ? }, ? ? ...... ? ]
三、profile触发方法
Android12及其的更高的版本需要使用task_profiles命令来激活profile配置。
task_profiles MaxPerformance
init.xxx.rc文件中的配置如下:

在Android 12以前使用writepid命令,如下:
writepid /dev/cpuctl/top-app/tasks
?Android 12以后writepid命令将不再使用。
四、Android CGroup API介绍
| 类型 | API 和定义 |
|---|
| profile操作相关函数 aosp/system/core/libprocessgroup/include/processgroup/processgroup.h | bool | SetTaskProfiles(int tid,?const std::vector& profiles) 将?profiles?中指定的任务配置文件应用于由线程 ID (tid) 使用其?tid?参数指定的线程。 | bool | SetProcessProfiles(uid_t uid,?pid_t pid,?const std::vector& profiles) 将?profiles?中指定的任务配置文件应用于由其用户 ID 和进程 ID 使用?uid?和?pid?参数指定的进程 | bool | CgroupGetControllerPath(const std::string& cgroup_name,?std::string* path) 返回值指示?cgroup_name?指定的 cgroup 控制器是否存在;如果为?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?变量设为与该配置文件属性相关联的文件的路径,以及由其线程 ID 使用?tid?参数指定的线程。 | bool | UsePerAppMemcg() 返回值指示系统是否配置为使用应用级别内存 cgroup。 |
五、其他
在Android12及更高的版本中,我们可以根据AndroidAPI级别或从Vendor,来修改胡哦替换默认cgroup.json和task_profiles.json文件。
前面已经贴出了端上的配置文件的路径,常见如下如下:
/system/etc/cgroups.json /system/etc/task_profiles.json
/system/etc/task_profiles/task_profiles_<API level>.json /system/etc/task_profiles/cgroups_<API level>.json /vendor/etc/cgroups.json /vendor/etc/task_profiles.json
Android 系统会按照以下顺序加载 cgroup 和 task_profile 文件:
- 默认 cgroups.json 和 task_profiles.json 文件。
- 特定于 API 级别的文件(如果存在)。
- vendor 分区文件(如果存在)。
|