最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

一文圖解|c(diǎn)group 設(shè)計(jì)分析(Docker底層技術(shù))

2022-10-15 17:17 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

cgroup 可能很多人都不了解,但提起 Docker 估計(jì)每個(gè)后端程序員都了解過。是的,Docker 已經(jīng)成為程序員必須掌握的技術(shù)之一了。Docker 主要解決了傳統(tǒng)虛擬機(jī)啟動(dòng)慢、占用大量資源的缺點(diǎn)。

當(dāng)然,本文的重點(diǎn)并不是 Docker,而是 Docker 的底層支撐技術(shù) cgroup。可以這樣說,沒有 cgroup 就沒有 Docker。

什么是 cgroup

cgroup 的全稱為 control group,中文翻譯為 控制組。主要用于控制進(jìn)程組對某種資源的使用,這些資源包括但不限于:內(nèi)存、CPU、I/O 和 網(wǎng)絡(luò) 等。

如下圖所示,使用 cgroup 來限制進(jìn)程組對內(nèi)存的使用:



在上圖中,我們創(chuàng)建了 2 個(gè) cgroup(每個(gè) cgroup 有 4 個(gè)進(jìn)程),并且限制它們各自最多只能使用 2GB 的內(nèi)存。如果使用超過 2GB 的內(nèi)存,那么將會(huì)觸發(fā) OOM(Out Of Memory) 錯(cuò)誤。

cgroup 通過把進(jìn)程劃分成控制組(一個(gè)控制組包含一個(gè)或多個(gè)進(jìn)程),并且可以對控制組進(jìn)行資源使用的控制,也就是說 cgroup 作用對象是控制組。

cgroup 提供了將進(jìn)程組織成控制組的能力,然后通過使用 資源控制子系統(tǒng)(cgroup_subsys) 來對控制組進(jìn)行資源使用的控制,cgroup 支持的 資源控制子系統(tǒng) 有以下幾種:

  • cpu子系統(tǒng):限制 CPU 的使用。

  • memory子系統(tǒng):限制內(nèi)存使用。

  • cpuset子系統(tǒng):可以為進(jìn)程組分配單獨(dú)的 CPU 或者內(nèi)存節(jié)點(diǎn)。

  • cpuacct子系統(tǒng):統(tǒng)計(jì)CPU group的使用情況。

  • blkio子系統(tǒng):限制I/O,一般用于磁盤。

  • devices子系統(tǒng):限制進(jìn)程使用的設(shè)備。

  • freezer子系統(tǒng):可以掛起和恢復(fù)進(jìn)程組。

  • net_cls子系統(tǒng):可以標(biāo)記進(jìn)程組的網(wǎng)絡(luò)數(shù)據(jù)包,使用 tc 模塊(traffic control)對數(shù)據(jù)包進(jìn)行控制。

也就是說,cgroup 通過把進(jìn)程組織成 控制組,然后通過 資源控制子系統(tǒng) 來對 控制組 進(jìn)行資源使用的限制,所以 cgroup 的分析可以分成兩部分:cgroup框架 和 資源控制子系統(tǒng)。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)? ?

cgroup 源碼分析

cgroup 的設(shè)計(jì)還是比較復(fù)雜的,主要是因?yàn)?cgroup 涉及多種資源的控制,并且 cgroup 通過虛擬文件系統(tǒng)來組織進(jìn)程控制組,所以導(dǎo)致 cgroup 的實(shí)現(xiàn)變得復(fù)雜難懂。

cgroup 的概念和使用可以參考這篇文章:《cgroup介紹》。

為了不會(huì)讓大家陷入枯燥的概念和源碼之中,本文主要通過以設(shè)計(jì)者的角度來分析 cgroup 的設(shè)計(jì)與實(shí)現(xiàn)。

OK,Let's go!

1. 設(shè)計(jì)一個(gè)簡單的 cgroup

如果讓你來設(shè)計(jì)一個(gè)限制進(jìn)程組對內(nèi)存使用的方案,你會(huì)怎么設(shè)計(jì)呢?

最簡單的方法就是,創(chuàng)建一個(gè)內(nèi)存使用的計(jì)數(shù)器,然后將進(jìn)程組中所有的進(jìn)程都指向這個(gè)計(jì)數(shù)器。當(dāng)進(jìn)程組的進(jìn)程申請內(nèi)存時(shí),就增加計(jì)數(shù)器的值,如果計(jì)數(shù)器超過限制就觸發(fā)錯(cuò)誤。如下圖所示:


上圖中計(jì)數(shù)器的 limit 字段表示限制進(jìn)程中使用的最大內(nèi)存數(shù),而 count 字段表示當(dāng)前進(jìn)程使用的內(nèi)存數(shù)。每當(dāng)進(jìn)程組中的進(jìn)程申請內(nèi)存時(shí),都需要增加計(jì)數(shù)器的 count 字段,并且比較 count 是否已經(jīng)超出 limit 的限制。

數(shù)據(jù)結(jié)構(gòu)可以這樣設(shè)計(jì):


我們通過鏈表來將進(jìn)程組織成進(jìn)程組,并且在計(jì)數(shù)器中增加一個(gè) task_group 字段,讓其指向進(jìn)程組。當(dāng)進(jìn)程組中的進(jìn)程申請內(nèi)存時(shí),可以通過指針來找到對應(yīng)的計(jì)數(shù)器,并且增加計(jì)數(shù)器的 count 字段。

就這樣,我們設(shè)計(jì)了一個(gè)簡單的 cgroup 功能。如果系統(tǒng)只有內(nèi)存這種資源的話,的確可以這樣設(shè)計(jì)。但是系統(tǒng)除了內(nèi)存,還有CPU、硬盤和網(wǎng)絡(luò)這些資源,所以 Linux 創(chuàng)建了一種比較通用的方式來組織進(jìn)程組。

2. 控制組

有了上面的雛形,cgroup 的很多概念就比較容易理解了,下面主要介紹一下 控制組 這個(gè)概念。

控制組 說白了就是一組進(jìn)程(進(jìn)程組),cgroup 就是用來限制 控制組 的資源使用。為了能夠方便地向一個(gè) 控制組 添加或者移除進(jìn)程(在命令行也能操作),內(nèi)核使用了 虛擬文件系統(tǒng) 來進(jìn)行管理 控制組。

我們可以把一個(gè) 控制組 當(dāng)成是一個(gè)目錄,由于目錄有層級(jí)關(guān)系,所以 控制組 也有層級(jí)關(guān)系,如下圖所示:



如上圖所示,控制組 是以目錄樹來組織的,每一個(gè)目錄代表一個(gè) 控制組。在內(nèi)核中,一個(gè)由 控制組 組成的目錄樹被稱為 層級(jí)(hierarchy)。

每個(gè)控制組目錄中,都有一個(gè)名為 tasks 的文件,用于保存當(dāng)前 控制組 包含的進(jìn)程列表。如果我們想向某個(gè) 控制組 添加一個(gè)進(jìn)程時(shí),可以把進(jìn)程的 PID 寫入到 tasks 文件中。例如:

我們也可以通過讀取 tasks 文件來查看某個(gè) 控制組 中的進(jìn)程列表,例如:

在內(nèi)核中,控制組使用 cgroup 結(jié)構(gòu)來表示,其定義如下:

內(nèi)核通過 cgroup 結(jié)構(gòu)的 sibling、children 和 parent 這3個(gè)字段來將 控制組 組織成一棵樹狀結(jié)構(gòu)。如下圖所示:



另外,cgroup 結(jié)構(gòu)的 subsys 字段表示當(dāng)前控制組關(guān)聯(lián)的子系統(tǒng)狀態(tài)對象,下面介紹 資源控制子系統(tǒng) 時(shí)將會(huì)詳細(xì)介紹。

在 Linux 內(nèi)核中,可以存在多個(gè) 層級(jí)(控制組樹),每個(gè)層級(jí)可以關(guān)聯(lián)一個(gè)或多個(gè) 資源控制子系統(tǒng),但同一個(gè) 資源控制子系統(tǒng) 不能關(guān)聯(lián)到多個(gè)層級(jí)中(也就是說,同一種 資源控制子系統(tǒng) 只能關(guān)聯(lián)到一個(gè)層級(jí))。如下圖所示:



在內(nèi)核中,層級(jí) 的根結(jié)點(diǎn)使用 cgroupfs_root 結(jié)構(gòu)來表示, 我們來看看其定義:


在 Linux 內(nèi)核中,有個(gè)名為 rootnode 的根層級(jí),在系統(tǒng)啟動(dòng)后,由內(nèi)核自動(dòng)創(chuàng)建并且初始化的層級(jí)。系統(tǒng)啟動(dòng)后,所有的資源控制子系統(tǒng)都關(guān)聯(lián)到此層級(jí)。rootnode 的定義如下:

如果用戶想把資源控制子系統(tǒng)關(guān)聯(lián)到其他層級(jí),那么可以使用 mount 命令來進(jìn)行掛載,如下命令所示:

上面的命令用于將內(nèi)存子系統(tǒng)重新關(guān)聯(lián)到 /sys/fs/cgroup/memory 這個(gè)層級(jí)。

3. 資源控制子系統(tǒng)

我們繼續(xù)來介紹 資源控制子系統(tǒng) (下面簡稱子系統(tǒng)) 這個(gè)重要的概念。

在 設(shè)計(jì)一個(gè)簡單的 cgroup 例子中,主要以內(nèi)存資源作為分析對象。但我們知道,計(jì)算機(jī)不單止只有內(nèi)存資源,還有譬如 CPU、硬盤和網(wǎng)絡(luò)等資源。所以,cgroup 不單止要控制內(nèi)存資源的使用,還要控制 CPU、硬盤和網(wǎng)絡(luò)等資源的使用。如下圖所示:



在上面的實(shí)例中,我們使用一個(gè)計(jì)數(shù)器來統(tǒng)計(jì)進(jìn)程組對內(nèi)存資源的使用情況,每個(gè) 控制組 都需要一個(gè)這樣的計(jì)數(shù)器來統(tǒng)計(jì)和限制進(jìn)程組對內(nèi)存資源的使用。

在 Linux 內(nèi)核中也有類似的 “計(jì)數(shù)器“,使用 cgroup_subsys_state 結(jié)構(gòu)來表示(我們稱它為 資源統(tǒng)計(jì)對象),其定義如下:


cgroup_subsys_state 結(jié)構(gòu)看起來非常簡單,這只是表面現(xiàn)象。內(nèi)核為了將所有的 資源統(tǒng)計(jì)對象 抽象化(也就是都能用 cgroup_subsys_state 指針來指向所有類型的 資源統(tǒng)計(jì)對象),才定義出這個(gè)通用的部分,實(shí)際上的 資源統(tǒng)計(jì)對象 是比較復(fù)雜的。

例如內(nèi)存的 資源統(tǒng)計(jì)對象 定義如下:

mem_cgroup 結(jié)構(gòu)與 cgroup_subsys_state 結(jié)構(gòu)的關(guān)系如下圖所示:



資源統(tǒng)計(jì)對象 必須與 控制組 綁定,才能實(shí)現(xiàn)限制 控制組 對資源的使用。前面我們了解到 cgroup 結(jié)構(gòu)中有個(gè)名為 subsys 的字段,如下代碼所示:

可以看出,subsys 字段是一個(gè) cgroup_subsys_state 結(jié)構(gòu)的數(shù)組,數(shù)組的大小為系統(tǒng)支持的 資源控制子系統(tǒng) 數(shù)(也就是說,數(shù)組上的每個(gè)槽位對應(yīng)著一個(gè)子系統(tǒng)資統(tǒng)計(jì)對象)。如下圖所示:



在 Linux 內(nèi)核中,一個(gè)進(jìn)程可以屬于多個(gè) 控制組,而每個(gè) 控制組 又關(guān)聯(lián)著一個(gè)或多個(gè) 資源統(tǒng)計(jì)對象。所以,一個(gè)進(jìn)程所關(guān)聯(lián)的 資源統(tǒng)計(jì)對象 是其所在 控制組 關(guān)聯(lián)的 資源統(tǒng)計(jì)對象 的集合。這句話有點(diǎn)難懂,我們用一幅圖來說明:



如上圖所示:

  • 進(jìn)程A 屬于控制組 /sys/fs/cgroup/memory/cgrp1/cgrp3 和控制組 /sys/fs/cgroup/cpu/cgrp2/cgrp3,所以 進(jìn)程A 就關(guān)聯(lián)了 mem_group A 和 task_group A 這兩個(gè)資源統(tǒng)計(jì)對象。

  • 進(jìn)程B 屬于控制組 /sys/fs/cgroup/memory/cgrp1/cgrp4 和控制組 /sys/fs/cgroup/cpu/cgrp2/cgrp3,所以 進(jìn)程B 就關(guān)聯(lián)了 mem_group B 和 task_group A 這兩個(gè)資源統(tǒng)計(jì)對象。

進(jìn)程通過 css_set 結(jié)構(gòu)來收集不同控制組的 資源統(tǒng)計(jì)對象,其定義如下:

在 進(jìn)程描述符結(jié)構(gòu)(task_struct) 中有個(gè)指向 css_set 結(jié)構(gòu)的指針,如下所示:

所以,當(dāng)把一個(gè)進(jìn)程添加到一個(gè) 控制組 時(shí),將會(huì)把 控制組 關(guān)聯(lián)的 資源統(tǒng)計(jì)對象 添加到進(jìn)程的 cgroups 字段中,從而使進(jìn)程受到這些 資源統(tǒng)計(jì)對象 的限制,結(jié)合圖10就比較容易理解了。

另外,資源子系統(tǒng)必須關(guān)聯(lián)到某個(gè)層級(jí)才能起到限制 控制組 使用的目的。每種資源子系統(tǒng)都由一個(gè)名為 cgroup_subsys 的結(jié)構(gòu)來描述,其定義如下:

從 cgroup_subsys 結(jié)構(gòu)的定義可以看出,其主要定義了一些方法和關(guān)聯(lián)的層級(jí)。比如:create 方法主要用于當(dāng)新建一個(gè) 控制組 時(shí),創(chuàng)建一個(gè)新的 資源統(tǒng)計(jì)對象 與其關(guān)聯(lián);而 root 字段指向關(guān)聯(lián)的層級(jí)根節(jié)點(diǎn)。

如內(nèi)存子系統(tǒng)的定義如下:

總結(jié)

本文主要分析了 cgroup 的設(shè)計(jì)與源碼實(shí)現(xiàn),不過聰明的讀者可能發(fā)現(xiàn)本文并沒有分析 cgroup 的邏輯代碼。

是的,本文并沒有分析具體的邏輯代碼實(shí)現(xiàn)。不過按照本文的設(shè)計(jì)分析,相信讀者能夠很容易看到 cgroup 的邏輯代碼實(shí)現(xiàn),有興趣的讀者可以自行閱讀源代碼。


原文作者:Linux內(nèi)核那些事





一文圖解|c(diǎn)group 設(shè)計(jì)分析(Docker底層技術(shù))的評論 (共 條)

分享到微博請遵守國家法律
通道| 平凉市| 衡阳县| 山丹县| 长垣县| 京山县| 百色市| 罗定市| 安仁县| 张家界市| 弥勒县| 吉首市| 青州市| 滨海县| 厦门市| 夏邑县| 甘泉县| 花莲市| 望奎县| 顺昌县| 阿拉善右旗| 巩义市| 教育| 托克托县| 桦南县| 山阴县| 曲水县| 施甸县| 长宁区| 保靖县| 香港| 巢湖市| 兰溪市| 岳普湖县| 绥棱县| 安图县| 贺州市| 香港| 广灵县| 宝清县| 金门县|