cgroup中的cgroup_subsys[]数组解析

来源:互联网 发布:外汇走势图软件 编辑:程序博客网 时间:2024/06/04 17:52
    全局数组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等等。这样定义的好处就是提高了代码复用率,减少了重复代码。各种相关定义不用再写一长串,只需要短短几行就可以定义完成。

0 0
原创粉丝点击