压缩相关
部署MAC上的Sublime Text + LaTex 中文环境
Cgroup介绍、应用实例及原理描述
Cgroup设计原理分析
Linux中,管理进程的数据结构是task_struct
#ifdef CONFIG_CGROUPS
/*Control Group info protected by css_set_lock*/
struct css_set *cgroups;
/*cg_list protected by css_set_lock and tsk->alloc_lock*/
struct list_head cg_list;
#endif
其中*cgroups指向css_set结构,css_set存储了与进程相关的cgroups信息。cg_list是一个嵌入式的list_head结构,将链到同一个css_set的进程组织成一个链表。
struct css_set{
atomic_t refcount;
struct hlist_node hlist;
struct list_head tasks;
struct list_head cg_links;
struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
struct rcu_head ruc_head;
};
其中,refcount是该css_set的引用数,因为一个css_set可以被多个进程公用,只要这些进程的cgroups信息相同。
hlist是嵌入的hlist_node,用于把所有css_set组成一个hash表,这样内核可以快速定位css_set。
tasks指向所有连到此css_set的进程指向的链表。
cg_links指向一个由struct_cg_group_link连城的链表。
subsys是一个指针数组,存储一组指向cgroup_subsys_state的指针,一个cgroup_subsys_state就是进程与一个特定子系统相关的信息。通过这个数组,进程可以获得相应的cgroup控制信息了。
struct cgroup_subsys_state{
struct cgroup *cgroup;
atomic_t refcnt;
unsigned long flags;
struct css_id *id;
};
*cgroup指向一个cgroup结构,也就是进程属于的cgroup。
task_struct-->css_set-->cgroup_subsys_state-->cgroup
这样进程就和cgroup连接起来了。
struct cgroup{
unsigned long flags;
atomic_t count;
struct list_head sibling;
struct list_head children;
struct cgroup *parent;
struct dentry *dentry;
struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]
struct cgroupfs_root *root;
struct cgroup *top_cgroup;
struct list_head css_sets;
struct list_head release_list;
struct list_head pidlists;
struct mutex pidlist_mutex;
struct rcu_head rcu_head;
struct list_head event_list;
spinlock_t event_list_lock;
};
sibling,children,parent三个嵌入的list_head负责将同一层级的cgroup连接成一颗cgroup树。
subsys指针数组,存储一组指向cgroup_subsys_state的指针。这组指针指向了此cgroup跟各个子系统相关的信息。类似css_set中。
root指向一个cgroupfs_root结构,就是cgroup所在层级对应的结构体。
top_cgroup指向了所在层级的根cgroup,即创建层级时自动创建的那个cgroup。
css_set指向一个由struct_cg_cgroup_link连成的链表。
struct cg_cgroup_link{
struct list_head cgrp_link_list;
struct cgroup *cgrp;
struct list_head cg_link_list;
struct css_set *cg;
};
cgrp_link_list连入到 cgroup->css_set链表,cgrp指向此cg_group_link相关的cgroup。
cg_link_list连入到css_set->cg_links指向的链表,cg指向此cg_group_link相关的css_set。
cgroup和css_set是一个多对多的关系,必须添加一个中间结构来将两者联系起来,这既是cg_cgroup_link的作用。cgrp和cg为此结构体的联合主键,cgrp_link_list和cg_link_list分别连入cgroup和css_set,使后两者都可以尽心遍历查询。
####为什么cgroup和css_set是多对多的关系?
一个进程对应一个css_set,一个css_set存储了一组进程跟各个子系统相关的信息,但是这些信息由可能不是从一个cgroup那里获得的,因为一个进程可以同时属于多个cgroup,只要这些cgroup不在同一个层级。
eg:
我们创建一个层级A,A上面附加了CPU和memory两个子系统,进程a属于A的根cgroup;创建一个层级B,B上面附加了ns和blkio两个子系统,进程a也属于B的根cgroup;那么进程a对应的CPU和memory是从A的根cgroup获得的,ns和blkio则是从B的根cgroup获得。因此一个css_set存储的cgroup_subsys_state可以对应多个cgroup。另一方面cgroup也存储了一组cgroup_subsys_state,这一组则是cgroup从所在的层级附加的子系统获得的。一个cgroup可以有多个进程,这些进程的css_set不一定都相同,因为有些进程可能还加入了其他cgroup,但是同一个cgroup中的进程与该cgroup关联的cgroup_subsys_state都受到该cgroup的管理,所以一个cgroup也可以对应多个css_set。
从前面的分析,我们可以看出从 task 到 cgroup 是很容易定位的,但是从 cgroup 获取此 cgroup 的所有的 task 就必须通过这个结构了。每个进程都回指向一个 css_set,而与这个 css_set 关联的所有进程都会链入到 css_set->tasks 链表,而 cgroup 又通过一个中间结构 cg_cgroup_link 来寻找所有与之关联的所有 css_set,从而可以得到与 cgroup 关联的所有进程。
上面这个图从整体结构上描述了进程与 cgroups 之间的关系。最下面的P代表一个进程。每一个进程的描述符中有一个指针指向了一个辅助数据结构css_set(cgroups subsystem set)。 指向某一个css_set的进程会被加入到当前css_set的进程链表中。一个进程只能隶属于一个css_set,一个css_set可以包含多个进程,隶属于同一css_set的进程受到同一个css_set所关联的资源限制。
上图中的”M×N Linkage”说明的是css_set通过辅助数据结构可以与 cgroups 节点进行多对多的关联。但是 cgroups 的实现不允许css_set同时关联同一个cgroups层级结构下多个节点。 这是因为 cgroups 对同一种资源不允许有多个限制配置。
一个css_set关联多个 cgroups 层级结构的节点时,表明需要对当前css_set下的进程进行多种资源的控制。而一个 cgroups 节点关联多个css_set时,表明多个css_set下的进程列表受到同一份资源的相同限制。