子系统mount完成后,Android会为每个子系统创建分组,这一步一般是在rc文件中配置的。如下图所示,top-app、foreground、key-background等都是一个分组,分组的创建方法非常简单就是在/dev/子系统下创建目录即可,例如mkdir /dev/blkio/foreground,就为blkio子系统创建了一个名为foreground的分组。
mkdir系统调用最终会调用到cgroup_mkdir()。cgroup_mkdir()主要完成两项工作:第一,调用cgroup_create()创建一个Cgroup并建立其与父group的关系;第二,调用cgroup_apply_control_enable()建立新建Cgroup与子系统的关系。
static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
umode_t mode)
{
struct cgroup *parent, *cgrp;
struct kernfs_node *kn;
int ret;
........................................................................
parent = cgroup_kn_lock_live(parent_kn, false);
if (!parent)
return -ENODEV;
//创建一个cgroup并建立其与父cgroup的关系
cgrp = cgroup_create(parent);
if (IS_ERR(cgrp)) {
ret = PTR_ERR(cgrp);
goto out_unlock;
}
/* create the directory */
kn = kernfs_create_dir(parent->kn, name, mode, cgrp);
if (IS_ERR(kn)) {
ret = PTR_ERR(kn);
goto out_destroy;
}
cgrp->kn = kn;
......................................................................
//创建默认节点
ret = css_populate_dir(&cgrp->self);
if (ret)
goto out_destroy;
//建立cgroup与子系统的关系
ret = cgroup_apply_control_enable(cgrp);
if (ret)
goto out_destroy;
.....................................................................
}
cgroup的成员struct cgroup_subsys_state self用于建立cgoup之间的关系:cgroup_subsys_state的parent指向父cgoup包含的cgroup_subsys_state,cgroup_subsys_state的list_head sibling链入到父cgoup包含cgroup_subsys_state的list_head children。通过cgroup_create()建立的新建cgroup与父cgroup的结构体关系如下图所示。
static struct cgroup *cgroup_create(struct cgroup *parent)
{
struct cgroup_root *root = parent->root;
struct cgroup *cgrp, *tcgrp;
int level = parent->level + 1;
int ret;
//分配内存空间
cgrp = kzalloc(sizeof(*cgrp) +
sizeof(cgrp->ancestor_ids[0]) * (level + 1), GFP_KERNEL);
....................................................................
//初始化
init_cgroup_housekeeping(cgrp);
cgrp->self.parent = &parent->self; //cgroup_subsys_state的parent指向父cgoup包含的cgroup_subsys_state
cgrp->root = root; //指向子系统cgroup_root
cgrp->level = level;
.....................................................................
//cgroup_subsys_state的list_head sibling链入到父cgoup包含cgroup_subsys_state的list_head children
list_add_tail_rcu(&cgrp->self.sibling, &cgroup_parent(cgrp)->self.children);
atomic_inc(&root->nr_cgrps);
cgroup_get(parent);
....................................................................
}
结构体struct cgroup_subsys_state也用于描述cgroup与子系统之间的联系。cgroup_create()创建的cgroup,成员subsys[]没有赋值,故在cgroup_apply_control_enable()中cgroup_css(dsct, ss)获取的值为空,需要进入if (!css)分支创建struct cgroup_subsys_state。
static int cgroup_apply_control_enable(struct cgroup *cgrp)
{
struct cgroup *dsct;
struct cgroup_subsys_state *d_css;
struct cgroup_subsys *ss;
int ssid, ret;
cgroup_for_each_live_descendant_pre(dsct, d_css, cgrp) {
for_each_subsys(ss, ssid) {
struct cgroup_subsys_state *css = cgroup_css(dsct, ss);
WARN_ON_ONCE(css && percpu_ref_is_dying(&css->refcnt));
if (!(cgroup_ss_mask(dsct) & (1 << ss->id)))
continue;
if (!css) {
css = css_create(dsct, ss);
if (IS_ERR(css))
return PTR_ERR(css);
}
if (css_visible(css)) {
ret = css_populate_dir(css);
if (ret)
return ret;
}
}
}
return 0;
}
新建struct cgroup_subsys_state的struct cgroup *cgroup成员指向cgroup_create()创建的cgroup,struct cgroup_subsys *ss成员指向对应子系统,建立起新建cgroup与子系统的关系。新建struct cgroup_subsys_state与其父cgroup_subsys_state(建立父cgroup与子系统关系的那个)也需建立关系,即新建struct cgroup_subsys_state的parent成员指向父cgroup_subsys_state,list_head sibling链入到父cgroup_subsys_state的list_head children。
static struct cgroup_subsys_state *css_create(struct cgroup *cgrp, struct cgroup_subsys *ss)
{
struct cgroup *parent = cgroup_parent(cgrp);
struct cgroup_subsys_state *parent_css = cgroup_css(parent, ss);
struct cgroup_subsys_state *css;
int err;
lockdep_assert_held(&cgroup_mutex);
//创建struct cgroup_subsys_state
css = ss->css_alloc(parent_css);
if (!css)
css = ERR_PTR(-ENOMEM);
if (IS_ERR(css))
return css;
//建立cgroup与子系统的关系
init_and_link_css(css, ss, cgrp);
err = percpu_ref_init(&css->refcnt, css_release, 0, GFP_KERNEL);
if (err)
goto err_free_css;
err = cgroup_idr_alloc(&ss->css_idr, NULL, 2, 0, GFP_KERNEL);
if (err < 0)
goto err_free_css;
css->id = err;
/* @css is ready to be brought online now, make it visible */
list_add_tail_rcu(&css->sibling, &parent_css->children);
cgroup_idr_replace(&ss->css_idr, css, css->id);
................................................................
}
static void init_and_link_css(struct cgroup_subsys_state *css,
struct cgroup_subsys *ss, struct cgroup *cgrp)
{
lockdep_assert_held(&cgroup_mutex);
cgroup_get(cgrp);
memset(css, 0, sizeof(*css));
css->cgroup = cgrp;
css->ss = ss;
css->id = -1;
INIT_LIST_HEAD(&css->sibling);
INIT_LIST_HEAD(&css->children);
css->serial_nr = css_serial_nr_next++;
atomic_set(&css->online_cnt, 0);
if (cgroup_parent(cgrp)) {
css->parent = cgroup_css(cgroup_parent(cgrp), ss);
css_get(css->parent);
}
BUG_ON(cgroup_css(cgrp, ss));
}
创建分组后的结构体关系如下。