深入淺出cgroup
一、什么是cgroup
Cgroup是linux內(nèi)核用來(lái)控制系統(tǒng)資源的機(jī)制,它將操作系統(tǒng)中的所有進(jìn)程以組為單位劃分,給這一組進(jìn)程定義對(duì)某一類(lèi)資源特定的訪(fǎng)問(wèn)權(quán)限。Cgroup用子系統(tǒng)(subsystem)來(lái)描述所能控制的系統(tǒng)資源,子系統(tǒng)具有多種類(lèi)型,每個(gè)類(lèi)型的子系統(tǒng)都代表一種系統(tǒng)資源,比如freezer、CPU、memory、IO等。以freezer子系統(tǒng)為例,這個(gè)子系統(tǒng)可以對(duì)一組線(xiàn)程批量?jī)鼋Y(jié),使用下面命令將打開(kāi)freezer子系統(tǒng):mount cgroup none /dev/freezer freezer
該命令將子系統(tǒng)掛載于/dev/freezer目錄,接下來(lái)可以在/dev/freezer目錄下創(chuàng)建若干個(gè)目錄,例如目錄top、background,每個(gè)目錄代表一組線(xiàn)程的資源分配行為,以cgroup實(shí)例描述,那么多級(jí)的目錄以cgroup實(shí)例的形式組成了一個(gè)樹(shù)形結(jié)構(gòu)。接下來(lái),可以給top組或者background組配置組內(nèi)進(jìn)程,echo 1199 > /dev/freezer/top/cgroup.procs當(dāng)前cgroup版本已經(jīng)不支持同一進(jìn)程組內(nèi)不同線(xiàn)程分屬于子系統(tǒng)內(nèi)不同cgroup。配置完top組內(nèi)的線(xiàn)程后,可以通過(guò)操作freezer.state節(jié)點(diǎn)配置組內(nèi)所有線(xiàn)程凍結(jié):echo FROZEN > /dev/freezer/top/freezer.state
解凍組內(nèi)所有線(xiàn)程:echo THAW > /dev/freezer/top/freezer.state
二、關(guān)鍵數(shù)據(jù)結(jié)構(gòu)以及相互關(guān)系
Cgroup子系統(tǒng)以cgroup_subsys結(jié)構(gòu)體描述,子系統(tǒng)中每個(gè)目錄由cgroup結(jié)構(gòu)體描述,這個(gè)目錄維護(hù)了一組線(xiàn)程的資源訪(fǎng)問(wèn)屬性。子系統(tǒng)的cgroup_subsys結(jié)構(gòu)體通過(guò)cgroup_root結(jié)構(gòu)體與子系統(tǒng)根目錄的cgroup建立聯(lián)系。目錄之間的樹(shù)形結(jié)構(gòu)通過(guò)cgroup結(jié)構(gòu)體中的cgroup_subsys_state結(jié)構(gòu)體描述,cgroup_subsys_state結(jié)構(gòu)體中有指向父目錄的parent 指針、以及兄弟和孩子鏈表。如圖:

由于線(xiàn)程與cgroup目錄具有多對(duì)多的關(guān)系,即一個(gè)cgroup目錄中含有多個(gè)線(xiàn)程,一個(gè)線(xiàn)程屬于不同子系統(tǒng)中的多個(gè)cgroup。linux通過(guò)css_set結(jié)構(gòu)體以及cgrp_cset_link結(jié)構(gòu)體來(lái)描述這個(gè)多對(duì)多的關(guān)系。css_set結(jié)構(gòu)代表一組線(xiàn)程,這些線(xiàn)程在各個(gè)子系統(tǒng)內(nèi)屬于同一cgroup目錄;cgrp_cset_link代表一個(gè)css_set和一個(gè)cgroup的映射關(guān)系,cgroup有一個(gè)cgrp_cset_link鏈表,通過(guò)這個(gè)鏈表可以找到這個(gè)?cgroup目錄下所有線(xiàn)程組成的css_set,同樣,css_set也維護(hù)一個(gè)cgrp_cset_link鏈表,通過(guò)這個(gè)鏈表,可以找到這個(gè)css_set在各個(gè)子系統(tǒng)中所歸屬的cgroup。如下圖css_set Z下的所有線(xiàn)程屬于freezer子系統(tǒng)的cgroupA以及memory子系統(tǒng)的cgroupC, css_set X下的所有線(xiàn)程屬于freezer子系統(tǒng)的cgroupA:

三、cgroup核心邏輯
當(dāng)某個(gè)子系統(tǒng)被掛載使能后,系統(tǒng)中所有線(xiàn)程默認(rèn)處于子系統(tǒng)根目錄所代表的cgroup實(shí)例中。?
1.?配置task到目標(biāo)cgroup
用戶(hù)或者應(yīng)用程序通過(guò)往cgroup.procs節(jié)點(diǎn)寫(xiě)入pid,cgroup.procs節(jié)點(diǎn)的write函數(shù)對(duì)應(yīng)到cgroup_procs_write。

cgroup_kn_lock_live函數(shù)根據(jù)當(dāng)前節(jié)點(diǎn)目錄解析到該目錄所對(duì)應(yīng)的cgroup實(shí)體,通過(guò)寫(xiě)權(quán)限檢查以后,進(jìn)入到主邏輯cgroup_attach_task函數(shù)里。

cgroup_migrate_prepare_dst函數(shù)保存當(dāng)前task所在css_set結(jié)構(gòu),
cgroup_migrate_prepare_dst函數(shù)利用保存的當(dāng)前css_set,查找是否存在滿(mǎn)足條件的目標(biāo)css_set,如果不存在滿(mǎn)足條件的目標(biāo)css_set,則創(chuàng)建一個(gè)新的css_set,插入多對(duì)多二維關(guān)系鏈表中。接下來(lái)cgroup_migrate函數(shù)將task從源css_set遷移到目標(biāo)css_set中。
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)? ??


2.?操控cgroup屬性
以freezer子系統(tǒng)為例,通過(guò)freezer.state節(jié)點(diǎn)控制cgroup組的凍結(jié)與解凍,這個(gè)節(jié)點(diǎn)對(duì)應(yīng)到freezer_write函數(shù),實(shí)際的邏輯在freezer_change_state函數(shù)中。

freezer_change_state函數(shù)第一個(gè)參數(shù)屬于freezer結(jié)構(gòu)體,它通過(guò)內(nèi)嵌的cgroup_subsys_state結(jié)構(gòu)與cgroup關(guān)聯(lián),也就是說(shuō)每個(gè)freezer結(jié)構(gòu)體直接對(duì)應(yīng)到freezer子系統(tǒng)的一個(gè)目錄。接下來(lái)看函數(shù)邏輯,css_for_each_descendant_pre循環(huán)體里對(duì)當(dāng)前目錄以及每個(gè)子孫目錄所代表cgroup實(shí)體執(zhí)行freezer_apply_state函數(shù)。freezer_apply_state函數(shù)通過(guò)調(diào)用freeze_cgroup和unfreeze_cgroup函數(shù)實(shí)際操作cgroup內(nèi)每個(gè)task的凍結(jié)與解凍。
四、小結(jié)
cgroup除了實(shí)現(xiàn)了freezer子系統(tǒng),還實(shí)現(xiàn)了控制組IO調(diào)度的blkio cgroup、控制cpu核資源組分配的cpuset cgroup、控制cpu運(yùn)行時(shí)間組分配的cpu cgroup、控制memory組分配的momory cgroup以及控制網(wǎng)絡(luò)帶寬組分配的cls_net cgroup,相關(guān)代碼讀者可自行研究。
原文作者:內(nèi)核工匠
