Linux源码cgroup_init_early
阅读数:255 评论数:0
跳转到新版页面分类
Linux
正文
一、概述
在Linux内核中,控制组(cgroups)是一个功能,它允许内核对进程进行分组,并对这些分组施加不同类型的资源限制和监控。控制组可以用来限制资源使用(如CPU时间、系统内存、网络带宽等),确保进程之间的资源分配公平,或者记录进程的资源使用情况。
cgroup_init_early
函数是在内核启动过程中,相对较早的阶段调用的,目的是进行控制组子系统的早期初始化。这个函数设置了控制组所需的一些基础结构,以便在内核的启动过程中后续可以完成更多的初始化工作。
早期初始化通常包括:
- 设置控制组的基础数据结构。
- 初始化控制组的层级和根控制组。
- 为系统中的每个可用控制器(如CPU、内存、IO等)准备控制组子系统。
这个早期初始化是必要的,因为控制组可能会影响到随后的内核初始化过程,例如,某些内核线程可能需要被放置到特定的控制组中。cgroup_init_early
确保了当这些线程被创建时,控制组子系统已经足够初始化,可以对它们进行分类和管理。
cgroup_init_early
通常在内核初始化代码的start_kernel
函数中被调用,这是内核启动过程中调用的主要函数之一。在这个函数中,内核会按照特定的顺序调用不同的初始化函数,以设置整个操作系统运行所需的各种组件。
需要注意的是,cgroup_init_early
只是控制组初始化过程中的一个步骤,整个控制组子系统的初始化包括多个阶段,其中包括后续的cgroup_init
函数,它在系统引导过程的稍后阶段完成更多的初始化工作。
二、cgroup
实现进程组,分配或限制进程组使用的资源(这部分主要由各个subsystem完成)。
另一个角度,在研究代码的时候,我们更愿意将cgroup理解为一种控制资源的行为。比如:我想控制进程的CPU使用率为20%,那么我可以创建一个cgroup,这个cgroup的作用就是控制指定进程的cpu使用率为20%。
cgroup是有层次结构的,所有的cgroup以树状分层(hierarchy)的形式被组织在一起。
三、subsystem
cpu subsystem:指定进程组能使用的CPU;
memmory subsystem:指定进程组能使用的内存量,并编写内存使用量报告;
cpuset subsystem:指定进程组能使用的各CPU和节点集;
freezer subsystem:可停止进程组状态或启动;
cpuacct subsystem:对进程组使用的CPU资源编写报告;
blkio:设置对模块设备的输入输出限制;
devices:设置进程组能使用的设备;
四、数据结构
进程需要与cgroup以subsystem建立联系,关键在于css_set结构体。首先,每个进程都可以对应一个css_set结构体,进程对应一个task_struct结构体,每个task_struct结构体中有一个css_set类型的成员指针cgroups
//Control Groups
#ifdef CONFIG_CGROUPS
/* Control Group info protected by css_set_lock: */
struct css_set __rcu *cgroups;
/* cg_list protected by css_set_lock and tsk->alloc_lock: */
struct list_head cg_list;
#endif
cgroups指针指进程对应的css_set结构体css_set结构体定义在/linux/include/cgroup-defs.h中,每个进程可以有自己的css_set结构体(由进程的.cgroup指向),css_set结构体中有对应的cgroup_subsys_state指针数组,通过cgroup_subsys_state可以找到对应的cgroup_subsys。如此进程与cgroup_subsys的联系就建立了。
所以定义了一个结构体叫做cgrp_cset_link
/*
* A cgroup can be associated with multiple css_sets as different tasks may
* belong to different cgroups on different hierarchies. In the other
* direction, a css_set is naturally associated with multiple cgroups.
* This M:N relationship is represented by the following link structure
* which exists for each association and allows traversing the associations
* from both sides.
*/
struct cgrp_cset_link {
/* the cgroup and css_set this link associates */
struct cgroup *cgrp;
struct css_set *cset;
/* list of cgrp_cset_links anchored at cgrp->cset_links */
struct list_head cset_link;
/* list of cgrp_cset_links anchored at css_set->cgrp_links */
struct list_head cgrp_link;
};
一个cgroup可能关联多个css_sets(即对不同的进程可能使用了相同的控制行为),另一方面,一个css_set通常关联多个cgroup(即对一进程使用多个控制行为)。cgroup和css_set的这种M:N的对应关系可以用struct cgrp_cset_link结构体表示,该结构体用于连接css_set与cgroup的架构。
初始化代码
start_kernel函数中会调用cgroup_init_early函数进行cgroup的初始化。其实对cgroup的初始化分两次,分别是cgroup_init_early和cgroup_init。这么做的原因,系统初始化阶段需要使用一些subsystem,先对这一部分进行初始化。