Linux Cgroup淺析


cgroup從2.6.4引入linux內核主線,目前默認已啟用該特性。在cgroup出現之前,只能對一個進程做資源限制,比如通過sched_setaffinity設置進程cpu親和性,使用ulimit限制進程打開文件上限、棧大小等。

cgroups是Linux下控制一個(或一組)進程的資源限制機制,全稱是control groups,可以對cpu、內存等資源做精細化控制,比如目前很多的Docker在Linux下就是基於cgroups提供的資源限制機制來實現資源控制的;除此之外,開發者也可以指直接基於cgroups來進行進程資源控制,比如8核的機器上部署了一個web服務和一個計算服務,可以讓web服務僅可使用其中6個核,把剩下的兩個核留給計算服務。cgroups cpu限制除了可以限制使用多少/哪幾個核心之外,還可以設置cpu占用比(注意占用比是各自都跑滿情況下的使用比例,如果一個cgroup空閑而另一個繁忙,那么繁忙的cgroup是有可能占滿整個cpu核心的)。

本文主要討論下cgroups概念及原理,然后分析下cgroups文件系統概念,最后對cgroups做個總結,關於cgroups的使用實踐可以參考網上資料,這里不再贅述。

cgroups概念

從實現角度來看,cgroups實現了一個通用的進程分組框架,不同資源的具體管理工作由各cgroup子系統來實現,當需要多個限制策略比如同時針對cpu和內存進行限制,則同時關聯多個cgroup子系統即可。

cgroups子系統

cgroups為每種資源定義了一個子系統,典型的子系統如下:

  • cpu 子系統,主要限制進程的 cpu 使用率。
  • cpuacct 子系統,可以統計 cgroups 中的進程的 cpu 使用報告。
  • cpuset 子系統,可以為 cgroups 中的進程分配單獨的 cpu 節點或者內存節點。
  • memory 子系統,可以限制進程的 memory 使用量。
  • blkio 子系統,可以限制進程的塊設備 io。
  • devices 子系統,可以控制進程能夠訪問某些設備。
  • net_cls 子系統,可以標記 cgroups 中進程的網絡數據包,然后可以使用 tc 模塊(traffic control)對數據包進行控制。
  • freezer 子系統,可以掛起或者恢復 cgroups 中的進程。
  • ns 子系統,可以使不同 cgroups 下面的進程使用不同的 namespace。

每個子系統都是定義了一套限制策略,它們需要與內核的其他模塊配合來完成資源限制功能,比如對 cpu 資源的限制是通過進程調度模塊根據 cpu 子系統的配置來完成的;對內存資源的限制則是內存模塊根據 memory 子系統的配置來完成的,而對網絡數據包的控制則需要 Traffic Control 子系統來配合完成。

cgroups原理

關於cgroups原理,可以從進程角度來剖析相關數據結構之間關系,Linux 下管理進程的數據結構是 task_struct,其中與cgrups相關屬性如下:

// 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

每個進程對應一個css_set結構,css_set存儲了與進程相關的cgropus信息。cg_list是一個嵌入的 list_head 結構,用於將連到同一個 css_set 的進程組織成一個鏈表。進程和css_set的關系是多對一關系,tasks表示關聯的多個進程。

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

subsys 是一個指針數組,存儲一組指向 cgroup_subsys_state 的指針,通過這個指針進程可以獲取到對應的cgroups信息,一個 cgroup_subsys_state 就是進程與一個特定子系統相關的信息,cgroup_subsys_state結構體如下:

struct cgroup_subsys_state {
	struct cgroup *cgroup;
	atomic_t refcnt;
	unsigned long flags;
	struct css_id *id;
};

cgroup 指針指向了一個 cgroup 結構,也就是進程屬於的 cgroup,進程受到子系統控制就是加入到特定的cgroup來實現的,就是對應這里的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 跟各個子系統相關的信息,也就是說一個cgroup可以關聯多個子系統,二者關系是多對多關系。

Linux下的cgroups的數據結構圖示如下:

cgroups 層級結構

在cgrups中一個task任務就是一個進程,一個進程可以加入到某個cgroup,也從一個進程組遷移到另一個cgroup。一個進程組的進程可以使用 cgroups 以控制族群為單位分配的資源,同時受到 cgroups 以控制族群為單位設定的限制。多個cgroup形成一個層級結構(樹形結構),cgroup樹上的子節點cgroup是父節點cgroup的孩子,繼承父cgroup的特定的屬性。注意:cgroups層級只會關聯某個子系統之后才能進行對應的資源控制,一個子系統附加到某個層級以后,這個層級上的所有cgroup都受到這個子系統的控制。cgroup典型應用架構圖如下:

cgroups文件系統

Linux 使用了多種數據結構在內核中實現了 cgroups 的配置,關聯了進程和 cgroups 節點,那么 Linux 又是如何讓用戶態的進程使用到 cgroups 的功能呢? Linux內核有一個很強大的模塊叫 VFS (Virtual File System)。 VFS 能夠把具體文件系統的細節隱藏起來,給用戶態進程提供一個統一的文件系統 API 接口。 cgroups 也是通過 VFS 把功能暴露給用戶態的,cgroups 與 VFS 之間的銜接部分稱之為 cgroups 文件系統。通過cgroups適配VFS,用戶可以使用VFS接口來操作cgroup功能。

VFS 是一個內核抽象層(通用文件模型),能夠隱藏具體文件系統的實現細節,從而給用戶態進程提供一套統一的 API 接口。VFS 使用了一種通用文件系統的設計,具體的文件系統只要實現了 VFS 的設計接口,就能夠注冊到 VFS 中,從而使內核可以讀寫這種文件系統。 這很像面向對象設計中的抽象類與子類之間的關系,抽象類負責對外接口的設計,子類負責具體的實現。其實,VFS本身就是用 c 語言實現的一套面向對象的接口。

小結

cgroups是Linux下控制一個(或一組)進程的資源限制機制,cgroup通過關聯單個/多個子系統定義了一套限制策略來限制CPU/內存等資源,子系統上限制策略相當於一套配置,需要內核中對應模塊配合來完成資源限制功能,比如對 cpu 資源的限制是通過進程調度模塊根據 cpu 子系統的配置來完成的等。

注意cgroups資源限制是針對cgroup為單位的,不管cgroup下是有一個進程還是多個進程。Docker下的容器內所有進程就是屬於同一組cgroup管理之下的,比如限制CPU使用,限制內存大小等。

推薦閱讀


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM