create new cgroup
该过程就是mkdir/cgroup/cpu/test_cpu:在一个/cgroup/cpu hierarchy上创建一个cgroup,下面的bt是创建一个cpu hierarchy下的cgroup:
mkdir /cgroup/cpu/test_cpu
74447177 8388 (mkdir) call trace:
0xffffffff8105fe80 : cpu_cgroup_create+0x0/0x40[kernel]
0xffffffff810c1021 :cgroup_mkdir+0x161/0x540 [kernel]
0xffffffff811850a7 :vfs_mkdir+0xa7/0x100 [kernel]
0xffffffff8118816e :sys_mkdirat+0xfe/0x120 [kernel]
0xffffffff811881a8 : sys_mkdir+0x18/0x20[kernel]
0xffffffff8100b0f2 :system_call_fastpath+0x16/0x1b [kernel]
在cgroup_mkdir里会直接调用cgroup_create(这里可能被编译器优化了),它先为该cgroup所属的每个subsys创建一个cgroup_subsys_state,并初始化:
for_each_subsys(root, ss) {
struct cgroup_subsys_state*css = ss->create(ss, cgrp);
init_cgroup_css(css, ss,cgrp);
…
}
通过该cgroup->subsys[]可以获得该cgroup的所有cgroup_subsys_state,同样通过cgroup_subsys_state->cgroup可以知道该cgroup_subsys_state所属的cgroup。以后cgroup与subsys的group控制体的转换都是通过该结构来完成。
cpu_cgroup_create最终会通过sched_create_group(继承父cgroup)来生成一个task_group(即cpu子系统的group控制体结构),它包含了该cgroup的se,cfs_rq,shares等(在介绍cpu子系统的时候,我们再详细讨论)。
创建完成cgroup_subsys_state后就是生成该目录cgroup_create_dir,及生成子系统的文件cgroup_populate_dir:
74447240 8388 (mkdir) call trace:
0xffffffff81054e60 :cpu_cgroup_populate+0x0/0x30 [kernel]
0xffffffff810c007a :cgroup_populate_dir+0x7a/0x110 [kernel]
0xffffffff810c11fc : cgroup_mkdir+0x33c/0x540[kernel]
0xffffffff811850a7 :vfs_mkdir+0xa7/0x100 [kernel]
0xffffffff8118816e :sys_mkdirat+0xfe/0x120 [kernel]
0xffffffff811881a8 : sys_mkdir+0x18/0x20[kernel]
0xffffffff8100b0f2 :system_call_fastpath+0x16/0x1b [kernel]
在创建cgroup目录的时候(cgroup_create_dir)会将该cgroup保存在dentry->d_fsdata = cgrp里,这样就将目录与该cgroup关联起来,当需要操作该目录下的文件时,就通过从这里取得它所属的cgroup;同样在生成每个文件的时候(cgroup_add_file)会把该文件的cftype保存到dentry->d_fsdata = (void *)cft,当在操作该文件的时候,将根据它定义的方法来完成。
简而言之,该过程完成cgroup结构的创建包括该cgroup所属的所有子系统的cgroup_subsys_state,然后相应的目录及文件,并把这些文件与该cgroup绑定起来。这里并没有建立css_set与该cgroup的关系,因为mkdir时该cgroup还没有attach任何进程,所以也不会有css_set与它有关系。