[Android Cgroup层次关系] 三、创建分组

        子系统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_statelist_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));
}

创建分组后的结构体关系如下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值