Linux Cgroup v1系列中文翻譯(1):控制組Control Group

来源:https://www.cnblogs.com/aosp/archive/2022/06/05/16343334.html
-Advertisement-
Play Games

英文原文:https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cgroups.html 1 控制組 1.1 什麼是控制組? 控制組(Control Group)提供一種機制,把一組任務(task)及其子任務整合/分割成具有特殊行為 ...


英文原文:https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cgroups.html

1 控制組

1.1 什麼是控制組?

控制組(Control Group)提供一種機制,把一組任務(task)及其子任務整合/分割成具有特殊行為的分層化的分組(groups)。

定義:
控制組(cgroup),把一組任務跟一個或者多個子系統(subsystem)的一組參數進行關聯。

分組(subsystem),是一種模塊,利用cgroup提供的任務分組功能,以特定的方式來實現任務組。分組(subsystem)一般是資源控制器(resource controller),調度資源或者設置資源限制,但是他也可以是管理一組進程的任何方法,例如虛擬子系統。

分層(hierachy),是一組樹形結構的控制組,系統中的每個任務都會處在分層的控制組和子系統中,每個子系統有控制組相關的系統狀態。每個分層都有一個控制組虛擬文件系統實例。

在任何時候,可以有多個激活的任務組分層。每個分層是系統中所有任務的一種隔離。

用戶級別的代碼可以根據cgroup虛擬文件系統中的名稱創建和銷毀控制組,指定和查詢任務被分配給哪個控制組,枚舉分配給控制組的任務PID。這些創建和分配隻影響該控制組文件系統相關的分層。

控制組的唯一作用就是簡化任務跟蹤。她的目標是其他子系統能掛載到通用控制組上,而這些通用控制組提供了新的控制組屬性,例如對控制組進程能訪問資源的統計和限制。舉個例子,cpusets允許把cpu和記憶體節點和每個控制組的任務進行關聯。

1.2 為什麼需要控制組?

在linux內核中,有多種用來做資源跟蹤的進程聚合方式,像cpusets,CKRM/ResGroups,UserBeanCounters和虛擬服務命名空間(namespace)。這些方式都需要瞭解進程分組/分割的基本概念,而這些在同一個分組(cgroup)中新產生的子進程作為他們的父進程。

內核的控制組補丁提供了最小的基本內核機制,根據需求有效的實現這種控制組。它對系統快速路徑(system fast paths)只有很小的影響,並提供了針對特定子系統的鉤子,像cpusets。

多級分層支持,允許分割任務到控制組,它明顯不同於一些有平行分層的子系統,允許每個分層作為自然的任務分隔,不必處理複雜的任務組合,而這些任務組合是出現在幾個不相關的子系統需要強制分配到同一個控制組樹的情況下。

在極端情況下,每個資源控制器或者子系統可能在單獨的分層中;另一種極端情況,所有的子系統可能隸屬於同一個分層。

有一個應用場景示例可能對多分層的理解有好處。假設一個有很多用戶(學生,教授,系統任務等)的大學伺服器,這個伺服器的資源規劃應該是下麵這樣子的:

CPU :          "Top cpuset"
                /       \
        CPUSet1         CPUSet2
           |               |
        (Professors)    (Students)   
        In addition (system tasks) are attached to topcpuset 
        (so that they can run anywhere) with a limit of 20%
 Memory : Professors (50%), Students (30%), system (20%)
   Disk : Professors (50%), Students (30%), system (20%)
Network : WWW browsing (20%), Network File System (60%), others (20%)
                        / \
        Professors (15%)  students (5%)

瀏覽器firefox/lynx算作WWW網路類,而 (k)nfsd算作NFS網路類。與此同時,取決於誰來運行它,Firefox/Lynx將共用cpu/memory類。

為了能對不同的資源劃分任務,管理員很容易就能運行腳本來接收執行通知,然後根據是誰來運行的瀏覽器,他可以執行下麵的命令:

# echo browser_pid > /sys/fs/cgroup/<restype>/<userclass>/tasks

在只有單個分層情況下,他現在可能必須要為每個啟動的瀏覽器創建一個單獨的控制組,然後關聯合適的網路和其他的資源類。這可能導致這種控制組的激增。

管理員可能臨時為一個學生的瀏覽器增加網路訪問,或者給一個學生的模擬器應用增加CPU算力。

下麵的方式可以直接寫PIDs到資源類中:

# echo pid > /sys/fs/cgroup/network/<new_class>/tasks
(after some time)
# echo pid > /sys/fs/cgroup/network/<orig_class>/tasks

沒有這種機制的話,管理員將不得不切分控制組成多個單獨的控制組,然後關聯新的控制組和新的資源類。

1.3 控制組是如何實現的?

控制組在內核中的擴展方式如下:

  • 系統中每個任務task一個引用計數指針指向css_set。
  • css_set包含一個指向cgroup_subsys_state對象的引用計數指針集合,每個控制組子系統在系統中註冊一個該對象。(省略部分)
  • 一個控制組分層文件系統能被從用戶空間掛載出來進行瀏覽和操作。
  • 可以根據PID枚舉隸屬於任何控制組的任務。

控制組的實現需要幾個簡單的鉤子鉤到內核其餘部分,但是不在關鍵性能的路徑上:

  • 在init/main.c中來初始化根控制組(root cgroups),在系統啟動時初始化css_set.
  • 在fork和exit時,從css_set中attach和detach任務。

除此之外,一個新的文件系統類型cgroup可以被掛載出來,以便能夠瀏覽和修改控制組。當掛載一個控制組分層(cgroup hierachy)的時候,你可以指定一個逗號分隔符的子系統列表來作為掛載選項。預設情況下,掛載控制組文件系統會試著掛載一個包含所有已註冊子系統的分層。

如果存在一個激活的分層有相同的子系統集合,它將被重用做新的掛載。如果沒有現存的分層匹配,以及現存分層中的任何子系統正在被使用,那麼掛載將會失敗(失敗號-EBUSY),否則,一個新的分層就被激活,跟請求的子系統關聯起來。
綁定新的子系統到激活的控制組分層中,或者從激活的控制組分層中解綁子系統,在當前是不可能,但是未來是可能的,但是它會充滿著嚴重的錯誤恢復(errot-recovery)問題。

當控制組文件系統被卸載時,如果有任何子控制組被創建在頂級控制組下,即使已經卸載完畢,分層仍會保持激活;如果沒有子控制組,那麼分層將會被停用。
沒有為控制組增加新的系統調用,對控制組的所有的查詢和修改的操作支持都是通過控制組文件系統。

在/proc下的每個任務都有一個新增的cgroup文件,對每個激活的分層來說,子系統命名和控制組名稱路徑都是相對控制組文件系統根路徑的。

每個控制組是由控制組文件系統中的目標表示的,它包含如下的文件來描述控制組:

  • tasks:隸屬於控制組的任務列表(以PID來表示),這個列表不是按序排列的。寫入線程ID到這個文件就表示移動線程到這個控制組。
  • cgroup.procs:線程組ID,這個列表不保證按序排列或者沒有重覆的TGIDs,如果需要的話,用戶空間應當排序或者uniquify這個列表。寫線程組ID到這個文件就會移動這個組中的所有線程到本控制組。
  • notify_on_release: 在exit退出時運行release agent。
  • release_agent: 用來釋放通知的路徑。(這個文件僅僅存在頂層控制組中)

其他的子系統,像cpusets可能會在每個控制組路目錄下添加額外的文件。

新的控制組可以通過mkdir系統調用或者shell命令來創建。控制組屬性,例如標簽,可以通過寫入該控制組目錄下的文件來修改。

嵌套控制組的命名分層結構允許分割大系統成嵌套的、動態可變的軟分區(soft-partitions)。

每個任務綁定到控制組時,在fork的時候會被該任務的子任務自動繼承,允許在系統中組織工作負載到相關的任務集合中。如果必要的控制組文件系統目錄允許,一個任務可以被重新綁定到任何控制組,

當任務從一個控制組移動到另一個控制組,他就會獲得一個新的css_set指針。如果有現存的css_set,帶有預期的可重用的控制組集合,那麼就可以重用,否則,就分配一個新的css_set。現有的css_set通過查詢哈希表來定位。

要允許從控制組來訪問css_sets,一個g_cgroup_link對象集合形成一個格柵(lattice);每個g_cgroup_link被鏈接到一個g_cgroup_links列表(省略......)

控制組中的任務集合可以通過引用該控制組的css_set來列舉。

使用linux虛擬文件系統vfs來表示控制組分層,最小化改動內核代碼,為控制組提供了常見的許可權和命名空間。

1.4 notify_on_release是做什麼的?

如果控制組中的notify_on_release標記被使能,那麼只要控制組中的最後一個任務離開(退出或者綁定到其他的控制組)並且最後的子控制組被移除,內核就會運行分層根目錄下的release_agent文件內容中定義的命令,提供廢棄的控制組的路徑名(相對控制組文件系統的掛載點)。這樣能自動移除廢棄的控制組。

在系統啟動的時候,根控制組中的notify_on_release的預設值是diabaled(0).其他的控制組在創建時候的預設值是他們的父控制組的notify_on_release的當前值。

控制組分層的release_agent路徑的預設值是空。

1.5 clone_children是做什麼的?

這個標簽僅僅影響cpuset控制器。如果clone_children標記在控制組中被使能enbale(1),一個新的cpuset控制組在初始化的時候就能複製父控制組的配置。

1.6 如何使用控制組?

要啟動一個將要包含在某個控制組中的新工作任務,使用cpuset控制組子系統,操作步驟如下:

1) mount -t tmpfs cgroup_root /sys/fs/cgroup
2) mkdir /sys/fs/cgroup/cpuset
3) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
4) Create the new cgroup by doing mkdir's and write's (or echo's) in
   the /sys/fs/cgroup/cpuset virtual file system.
5) Start a task that will be the "founding father" of the new job.
6) Attach that task to the new cgroup by writing its PID to the
   /sys/fs/cgroup/cpuset tasks file for that cgroup.
7) fork, exec or clone the job tasks from this founding father task.

舉個例子,下麵的命令序列將會創建一個名稱為“Charlie”的控制組,僅僅包含CPU2和3,記憶體節點1,在控制組中啟動一個子shell ‘sh’:

mount -t tmpfs cgroup_root /sys/fs/cgroup
mkdir /sys/fs/cgroup/cpuset
mount -t cgroup cpuset -ocpuset /sys/fs/cgroup/cpuset
cd /sys/fs/cgroup/cpuset
mkdir Charlie
cd Charlie
/bin/echo 2-3 > cpuset.cpus
/bin/echo 1 > cpuset.mems
/bin/echo $$ > tasks
sh
# The subshell 'sh' is now running in cgroup Charlie
# The next line should display '/Charlie'
cat /proc/self/cgroup

2 應用示例和語法

2.1 基本用法

創建、修改和使用控制組可以通過控制組虛擬文件系統來完成。

要掛載一個所有子系統都可用的控制組分層,輸入命令:

# mount -t cgroup xxx /sys/fs/cgroup

內核代碼解讀不了“xxx”,但是它會出現在/proc/mounts中,因此它就可以是你想用的有用的身份字元串。

註意:沒有用戶提前輸入的話,一些子系統不能工作。例如,如果cpusets被使能,用戶必須為每個已經創建但是還沒使用的控制組寫入數據到cpu和mem文件中。

正如1.2章節所述,我們為什麼需要控制組?你應該為每個你想要控制的資源或者資源組創建不同的控制組分層。因此,你可以掛載在/sys/fs/cgroup中tmpfs,然後為每個控制組資源或者資源組創建目錄:

# mount -t tmpfs cgroup_root /sys/fs/cgroup
# mkdir /sys/fs/cgroup/rg1

要掛載只有cpuset和memory子系統的控制組分層,輸入如下命令:

# mount -t cgroup -o cpuset,memory hier1 /sys/fs/cgroup/rg1

重新掛載控制組當前是支持的,但是不推薦使用。重新掛載允許改變子系統和release_agent。重新綁定幾乎沒有什麼用,它只在分層為空並且release_agent本身應當被常規fsnotify替換的時候才會生效。重新掛載在未來會被移除。

要定義分層的release_agent:

# mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" xxx /sys/fs/cgroup/rg1

註意,如果多次定義release_agent,將會返回失敗。

註意,子系統集合的變更當前被支持,僅限於由單個(根)控制組組成的分層。能夠隨時從現存的控制組分層綁定/解綁子系統,未來會考慮支持實現。

然後在/sys/fs/cgroup/rg1下,你能找到系統中的控制組樹。例如/sys/fs/cgroup/rg1也可以是容納整個系統的控制組。

如果你想要更改release_agent的值:

# echo "/sbin/new_release_agent" > /sys/fs/cgroup/rg1/release_agent

它也可以在重新掛載時更改。

如果你想在/sys/fs/cgroup/rg1下創建新的控制組:

# cd /sys/fs/cgroup/rg1
# mkdir my_cgroup

現在你想要用這個控制組來做些什麼的話:

# cd my_cgroup

在這個目錄下,你可以找到幾個文件:

# ls
cgroup.procs notify_on_release tasks
(plus whatever files added by the attached subsystems)

現在綁定你的當前shell到這個控制組:

# /bin/echo $$ > tasks

你也能在你的控制組內部創建控制組,在這個目錄下使用mkdir:

# mkdir my_sub_cs

要移除控制組,只要使用rmdir就可以:

# rmdir my_sub_cs

如果控制組正在使用中(內部有控制組,或者有進程綁定綁定,或者其他子系統相關的引用保持激活狀態),這操作就會失敗。

2.2 綁定進程

# /bin/echo PID > tasks

註意,這裡是PID而不是PIDs,一次只能綁定一個任務。如果你有幾個任務,只能一個個的綁定:

# /bin/echo PID1 > tasks
# /bin/echo PID2 > tasks
        ...
# /bin/echo PIDn > tasks

你也可以通過寫入0來綁定當前的shell任務:

# echo 0 > tasks

你也可以使用cgroup.procs文件來代替tasks文件,一次性移除線程組中的所有任務。寫入線程組中任何的任務PID到cgroup.procs中,線程組中的所有任務將會被綁定到該控制組。寫入0到cgroup.procs中就會移動當前寫任務的線程組中的所有任務。

註意:因為每個任務總是某個已掛載分層下的控制組的成員,要從當前控制組移除任務,你必須移動它到新的控制組(可能是根控制組),就是通過寫入新控制組的tasks文件的方式。

註意:由於受到一些控制組子系統的強制限制,移動進程到另外的控制組可能會失敗。

2.3 按名字掛載分層

當掛載控制組分層時傳遞name=選項,就會以給定的名字來關聯分層。這麼做是有用的,對於掛載一個已存在(pre-existing)的分層時,為了按名引用而不是按激活子系統的集合引用。每個分層或者是無名的或者是有一個唯一的名字。

名字應當匹配 [w.-]+

當傳遞name=選項給新的分層時,你需要手動定義子系統;當你給一個子系統命名一個名字,掛載所有子系統而什麼都沒有定義,這種行為是不被支持的。

子系統的名字作為分層的一部分會出現在/proc/mounts和/proc//cgroups中。

3 Kernel API

省略原文大概90行!我個人並不關註這一部分,所以沒有翻譯!!!

4 擴展屬性用法

控制組文件系統支持它的目錄和文件中擴展屬性的特定類型,當前支持的類型是:

Trusted (XATTR_TRUSTED)
Security (XATTR_SECURITY)

他們都需要設置CAP_SYS_ADMIN功能。

跟在tmpfs中一樣,控制組文件系統中的擴展屬性使用內核記憶體來存儲,建議保持最小使用。這就是為什麼用戶定義的擴展屬性不支持的原因,因為任何用戶都能這麼做並且沒有大小限制。

這個功能當前的已知用戶是SELINUX,用來限制控制組在容器中和systemd的使用,以便對諸如控制組(systemd為每個服務創建的控制組)中的主PID這樣的meta數據進行分類。

5 答疑

Q: 為什麼要使用'/bin/echo'?  
A: bash內嵌的echo命令不會檢查對write()調用的錯誤,如果你在控制組文件系統中使用它,你將不知道命令是否執行成功還是失敗。  

Q: 當我綁定很多進程時,只有第一行被真正綁定?  
A: 每次對write()的調用只能返回一個錯誤,所以你應該就放一個PID。 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、填空題 在種群增長預測問題中,若資源環境等因素是有限的,則應使用的微分方程模型為 Logistic模型 某種群分為 4 個年齡組, 各組的繁殖率分別為 0, 0.8, 1.8, 0.2, 存活率分別為 0.5, 0.7, 0.9, 0. 現各組的數量均為 100, 則該種群的的穩定分佈向量為 解 ...
  • 一、Postman Postman 是一個款 HTTP 請求模擬工具 首先演示一下 Postman 最基本的使用,創建一個 Spring Boot 項目,測試的代碼如下: import org.springframework.web.bind.annotation.GetMapping; impor ...
  • ## 進程與線程的區別 - 進程基本上相互獨立的,而線程存在於進程內,是進程的一個子集 - 進程擁有共用的資源,如記憶體空間等,供其內部的線程共用 - 進程間通信較為複雜 - 同一臺電腦的進程通信稱為 IPC(Inter-process communication) - 不同電腦之間的進程... ...
  • 哈工大軟體構造Lab2中Assert的使用總結,可供後來學子借鑒學習 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • 這是一個類似於記事本的文字處理器。與正常的記事本不同的是,它會將文本文檔進行加密,確保無法被常規的程式打開。 由於本人是一位業餘編程愛好者,對於“python之禪”之類的規則比較不以為然,因此本程式代碼也許有些許凌亂(當然不利於後期修改)。 這篇文章我早已發佈過,但當時只給出了代碼,並加了一些註釋。 ...
  • 最近在看 C++ 類繼承中的欄位記憶體佈局,我就很好奇 C# 中的繼承鏈那些 private 欄位都哪裡去了? 在記憶體中是如何佈局的,畢竟在子類中是無法訪問的。 一:舉例說明 為了方便講述,先上一個例子: internal class Program { static void Main(string ...
  • du Linux du (英文全拼:disk usage)命令用於顯示目錄或文件的大小。 du 會顯示指定的目錄或文件所占用的磁碟空間。 du命令作用是估計文件系統的磁碟已使用量,常用於查看文件或目錄所占磁碟容量。 du命令與df命令不同,df命令是統計磁碟使用情況,詳見linux命令詳解之df命令 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...