毕设论文相关知识索引笔记

压缩相关

速度之王-lz4压缩算法

使用tar+lz4+ssh更快的数据传输

Docker源码分析之Docker daemon启动和销毁

部署MAC上的Sublime Text + LaTex 中文环境

Cgroup介绍、应用实例及原理描述

Cgroup介绍、应用实例及原理描述

Linux资源管理之cgroups简介

CRIU support in Docker C/R

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_1

上面这个图从整体结构上描述了进程与 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下的进程列表受到同一份资源的相同限制。