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 可以基本從進程級別反應之間的響應關係。