cgroup底層研究

cgroup是一個內核的功能,他的作用是將系統中的進程進行分組化管理。docker、openshift就是基於cgroup上建立的。


相關概念


  • task 一個任務就是一個進程

  • control group  就是一個進程集合,可以把它理解成一個房間,每個房間都是相互隔離的。

  • hierachy(層級) control group存在父子的概念,負責可以使用子組裏的資源

  • subsystem 如果組內的進程需要工作,就必須要有cpu內存之類的資源,這就需要涉及到資源控制器,這個資源控制器就是subsystem。比如一個cpu控制器就是一個subsystem


cgroup結構



  • 一個層級可以有多個子系統,比如cpu、內存等,但是一個子系統只能附在一個層級上

  • 子組可以繼承父組

典型應用框架


cgroup設計原理

#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

cgroup作爲指針指向css_set(用於存放與進程有關的cgroup信息)

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 rcu_head;
};

refcount是css_set的引用計數,組裏加一個進程,refcount加1

hlist把css_set組織成hash表,使內核可以快速查找特定的css_set。

tasks指向所有連到此 css_set 的進程連成的鏈表。

cg_links 指向一個由 struct_cg_cgroup_link 連成的鏈表。

Subsys 是一個指針數組,存儲一組指向 cgroup_subsys_state 的指針。

一個 cgroup_subsys_state 就是進程與一個特定子系統相關的信息。通過這個指針數組,進程就可以獲得相應的 cgroups 控制信息了。以此就可以限制進程使用資源了。

task_struct->css_set->cgroup_subsys_state->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負責層級的劃分

一個進程對應一個css_set,一個css_set存儲了一組進程跟各子系統相關的信息。

我們創建一個層級 A,A 上面附加了 cpu 和 memory 兩個子系統,進程 B 屬於 A 的根 cgroup;然後我們再創建一個層級 C,C 上面附加了 ns 和 blkio 兩個子系統,進程 B 同樣屬於 C 的根 cgroup;那麼進程 B 對應的 cpu 和 memory 的信息是從 A 的根 cgroup 獲得的,ns 和 blkio 信息則是從 C 的根 cgroup 獲得的。

struct cgroupfs_root {
struct super_block *sb;
unsigned long subsys_bits;
int hierarchy_id;
unsigned long actual_subsys_bits;
struct list_head subsys_list;
struct cgroup top_cgroup;
int number_of_cgroups;
struct list_head root_list;
unsigned long flags;
char release_agent_path[PATH_MAX];
char name[MAX_CGROUP_ROOT_NAMELEN];
};

sb 指向該層級關聯的文件系統數據塊。

subsys_bits 和 actual_subsys_bits 分別指向將要附加到層級的子系統和現在實際附加到層級的子系統,在子系統附加到層級時使用。

top_cgroup 指向該層級的根 cgroup。number_of_cgroups 記錄該層級 cgroup 的個數。

root_list 是一個嵌入的 list_head,用於將系統所有的層級連成鏈表。

struct cgroup_subsys {
struct cgroup_subsys_state *(*create)(struct cgroup_subsys *ss,
struct cgroup *cgrp);
int (*pre_destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
int (*can_attach)(struct cgroup_subsys *ss,
 struct cgroup *cgrp, struct task_struct *tsk, bool threadgroup);
void (*cancel_attach)(struct cgroup_subsys *ss,
struct cgroup *cgrp, struct task_struct *tsk, bool threadgroup);
void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
struct cgroup *old_cgrp, struct task_struct *tsk, bool threadgroup);
void (*fork)(struct cgroup_subsys *ss, struct task_struct *task);
void (*exit)(struct cgroup_subsys *ss, struct task_struct *task);
int (*populate)(struct cgroup_subsys *ss, struct cgroup *cgrp);
void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cgrp);
void (*bind)(struct cgroup_subsys *ss, struct cgroup *root);
int subsys_id;
int active;
int disabled;
int early_init;
bool use_id;
#define MAX_CGROUP_TYPE_NAMELEN 32
const char *name;
struct mutex hierarchy_mutex;
struct lock_class_key subsys_key;
struct cgroupfs_root *root;
struct list_head sibling;
struct idr idr;
spinlock_t id_lock;
struct module *module;
};

從基本層次順序定義上來看,由 task_struct、css_set、cgroup_subsys_state、cgroup、cg_cgroup_link、cgroupfs_root、cgroup_subsys 等結構體組成的 CGroup 可以基本從進程級別反應之間的響應關係。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章