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使用,限制內存大小等。

推薦閱讀

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