cgroup中的cgroup_subsys[]数组解析

    全局数组cgroup_subsys[]在内核中应用很多,最常用的就是通过for_each_subsy()宏来遍历系统中的预定义的各个struct cgroup_subsys *ss:
#define for_each_subsys(ss, ssid)					\
	for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT &&		\
	     (((ss) = cgroup_subsys[ssid]) || true); (ssid)++)

    可以看到宏 "for_each_subsys"  就是遍历全局数组cgroup_subsys[]; 但是这个cgroup_subsys[]数组的各个元素是什么呢?它又在哪里定义的呢?
    说起来它还真的有点复杂,还是搞了那么些幺蛾子。它的定义在kernel/cgroup.c中:
/* generate an array of cgroup subsystem pointers */
#define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys,
static struct cgroup_subsys *cgroup_subsys[] = {
	#include <linux/cgroup_subsys.h>
};
#undef SUBSYS

    咦,奇怪,这个cgroup_subsys[]数组里面居然是一个头文件。编译器在编译的时候会展开头文件<linux/cgroup_subsys.h>:

...
SUBSYS(cpuset)
SUBSYS(cpu)
SUBSYS(cpuacct)
SUBSYS(io)
SUBSYS(memory)
SUBSYS(devices)
SUBSYS(freezer)
SUBSYS(net_cls)
SUBSYS(perf_event)
SUBSYS(net_prio)
SUBSYS(hugetlb)
SUBSYS(pids)
SUBSYS(debug)
.....
    为了更好的理解这个头文件内容,我去掉了一些边边角角,就得到上面的代码。即cgroup_subsys[]看起来有点像这样:
#define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys,
static struct cgroup_subsys *cgroup_subsys[] = {
	SUBSYS(cpuset)
	SUBSYS(cpu)
	SUBSYS(cpuacct)
	SUBSYS(io)
	SUBSYS(memory)
	SUBSYS(devices)
	SUBSYS(freezer)
	SUBSYS(net_cls)
	SUBSYS(perf_event)
	SUBSYS(net_prio)
	SUBSYS(hugetlb)
	SUBSYS(pids)
	SUBSYS(debug)
};
#undef SUBSYS
    我们还注意到"SUBSYS()" 在这里宏定义成了这个东西:

#define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys,
    将这个“SUBSYS”宏展开代入到cgroup_subsys[]中,看起来就是这样:
static struct cgroup_subsys *cgroup_subsys[] = {
	[cpuset_cgrp_id] = &cpuset_cgrp_subsys,
	[cpu_cgrp_id] = &cpu_cgrp_subsys,
	[cpuacct_cgrp_id] = &cpuacct_cgrp_subsys,
	[io_cgrp_id] = &_cgrp_subsys,
	[memory_cgrp_id] = &memory_cgrp_subsys,
	[devices_cgrp_id] = &devices_cgrp_subsys,
	[freezer_cgrp_id] = &freezer_cgrp_subsys,
	[net_cls_cgrp_id] = &net_cls_cgrp_subsys,
	[perf_event_cgrp_id] = &perf_event_cgrp_subsys,
	[net_prio_cgrp_id] = &net_prio_cgrp_subsys,
	[hugetlb_cgrp_id] = &_hugetlbcgrp_subsys,
	[pids_cgrp_id] = &pids_cgrp_subsys,
	[debug_cgrp_id] = &debug_cgrp_subsys,
};
    God,我们很接近真面目了,cgroup_subsys[]数组中的各个元素可以猜到就是&cpuset_cgrp_subsys,&cpuset_cgrp_subsys,&cpuacct_cgrp_subsys,&io_cgrp_subsys......这些就是cgroup中各个子系统cgroup_subsys的全局变量结构。这些xxx_cgrp_subsys全局变量在内核编译好后就已经初始化ok、分配好空间。

    我们拿cpu子系统struct cgroup_subsys cpu_cgrp_subsys这个结构来举例,它定义在kernel/sched/core.c文件中:

struct cgroup_subsys cpu_cgrp_subsys = {
	.css_alloc	= cpu_cgroup_css_alloc,
	.css_released	= cpu_cgroup_css_released,
	.css_free	= cpu_cgroup_css_free,
	.fork		= cpu_cgroup_fork,
	.can_attach	= cpu_cgroup_can_attach,
	.attach		= cpu_cgroup_attach,
	.legacy_cftypes	= cpu_files,
	.early_init	= 1,
};
    好了,说完了各个元素,我们再来说说数组中元素的index:"_x## _cgrp_id"。

    各个元素的索引"_x## _cgrp_id"也是通过SUBSY宏的把戏在include/linux/cgroup-defs.h中定义的:

/* define the enumeration of all cgroup subsystems */
#define SUBSYS(_x) _x ## _cgrp_id,
#define SUBSYS_TAG(_t) CGROUP_ ## _t, \
	__unused_tag_ ## _t = CGROUP_ ## _t - 1,
enum cgroup_subsys_id {
#include <linux/cgroup_subsys.h>
	CGROUP_SUBSYS_COUNT,
};
#undef SUBSYS_TAG
#undef SUBSYS
    有了前面对cgroup_subsys[]定义的分析,这里应该是轻车熟路了。即各个子系统的索引id "_x## _cgrp_id" 是通过枚举类型enum cgroup_subsys_id {} + <linux/cgroup_subsys.h> + SUBSYS(_x)宏来定义的。

    好了,这样以来,有了数组元素索引 和 数组元素,自然这个cgroup_subsys[]元素的定义也就终于真想大白了。

   你,懂了么?

    最后讲一点,为什么cgroup_subsys[]的定义要通过SUBSYS()宏 + "#include <linux/cgroup_subsys.h>" 的方式来定义呢?因为在内核中,有多个cgroup相关的结构都要用到子系统相关的名字的定义,如上面的xxx_cgrp_id以及xxx_cgrp_subsys等等。这样定义的好处就是提高了代码复用率,减少了重复代码。各种相关定义不用再写一长串,只需要短短几行就可以定义完成。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值