linux cgroups詳細(xì)介紹
從 2.6.24 版本開始,linux 內(nèi)核提供了一個叫做 cgroups(控制組)的特性。cgroups 就是 control groups 的縮寫,用來對一組進(jìn)程所占用的資源做限制、統(tǒng)計、隔離。也是目前輕量級虛擬化技術(shù) lxc (linux container)的基礎(chǔ)之一。每一組進(jìn)程就是一個控制組,也就是一個 cgroup。cgroups 分為幾個子系統(tǒng),每個子系統(tǒng)代表一種設(shè)施或者說是資源控制器,用來調(diào)度某一類資源的使用,如 cpu 時鐘、內(nèi)存、塊設(shè)備 等。在實現(xiàn)上,cgroups 并沒有增加新的系統(tǒng)調(diào)用,而是表現(xiàn)為一個 cgroup 文件系統(tǒng),可以把一個或多個子系統(tǒng)掛載到某個目錄。如
mount -t cgroup -o cpu cpu /sys/fs/cgroup/cpu
就將 cpu 子系統(tǒng)掛載在了 /sys/fs/cgroup/cpu 。也可以在一個目錄上掛載多個子系統(tǒng),甚至全部掛載到一個目錄也是可以的,不過我覺得,把每個子系統(tǒng)都掛載在不同目錄會有更好的靈活性。用 mount|awk '$5=="cgroup" {print $0}' 可以看到當(dāng)前掛載的控制組。用 cat /proc/cgroups 可以看到當(dāng)前所有控制組的狀態(tài)。下面這個腳本,可以把全部子系統(tǒng)各種掛載到各自的目錄上去。
#!/bin/bash</p> <p>cgroot="${1:-/sys/fs/cgroup}"
subsys="${2:-blkio cpu cpuacct cpuset devices freezer memory net_cls net_prio ns perf_event}"</p> <p>mount -t tmpfs cgroup_root "${cgroot}"
for ss in $subsys; do
mkdir -p "$cgroot/$ss"
mount -t cgroup -o "$ss" "$ss" "$cgroot/$ss"
done
看看那些目錄里都有些啥,比如 ls 一下 /sys/fs/cgroup/cpu。
cgroup.event_control cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release tasks
cgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat release_agent
其中 “cpu.” 開頭的就是這個子系統(tǒng)里特有的東西。其他的那些是每個子系統(tǒng)所對應(yīng)目錄里都有的。這些文件就是用來讀取資源使用信息和進(jìn)行資源限制的。要創(chuàng)建一個控制組,就在需要的子系統(tǒng)里創(chuàng)建一個目錄即可。如 mkdir /sys/fs/cgroup/cpu/foo 就創(chuàng)建了一個 /foo 的控制組。在新建的目錄里就會出現(xiàn)同樣一套文件。在這個目錄里,也一樣可以繼續(xù)通過創(chuàng)建目錄來創(chuàng)建 cgroup。也就是說,cgroup 是可以和目錄結(jié)構(gòu)一樣有層次的。對與每個子系統(tǒng)掛載點點目錄,就相當(dāng)于根目錄。每一條不同的路徑就代表了一個不同的 cgroup。在不同的子系統(tǒng)里,路徑相同就代表了同一個控制組。如,在 cpu、memory 中都有 foo/bar 目錄,就可以用 那 /foo/bar 來操作 cpu、memory 兩個子系統(tǒng)。對于同一個子系統(tǒng),每個進(jìn)程都屬于且只屬于一個 cgroup,默認(rèn)是在根 cgroup。層次結(jié)構(gòu)方便了控制組的組織和管理,對于某些配置項來說,層次結(jié)構(gòu)還和資源分配有關(guān)。另外,也可以修改某個目錄的 owner ,讓非 root 用戶也能操作某些特定的安全組。
cgroups 的設(shè)置和信息讀取是通過對那些文件的讀寫來進(jìn)行的。例如
# echo 2048 >/sys/fs/cgroup/cpu/foo/cpu.shares
就把 /foo 這個控制組的 cpu.shares 參數(shù)設(shè)為了 2048。
前面說,有些文件是每個目錄里共有的。那些就是通用的設(shè)置。其中,tasks 和 cgroups.procs 是用來管理控制組中的進(jìn)程的。要把一個進(jìn)程加入到某個控制組,把 pid 寫入到相應(yīng)目錄的 tasks 文件即可。如
# echo 5678 >/sys/fs/cgroup/cpu/foo/tasks
就把 5678 進(jìn)程加入到了 /foo 控制組。那么 tasks 和 cgroups.procs 有什么區(qū)別呢?前面說的對“進(jìn)程”的管理限制其實不夠準(zhǔn)確。系統(tǒng)對任務(wù)調(diào)度的單位是線程。在這里,tasks 中看到的就是線程 id。而 cgroups.procs 中是線程組 id,也就是一般所說的進(jìn)程 id 。將一個一般的 pid 寫入到 tasks 中,只有這個 pid 對應(yīng)的線程,以及由它產(chǎn)生的其他進(jìn)程、線程會屬于這個控制組,原有的其他線程則不會。而寫入 cgroups.procs 會把當(dāng)前所有的線程都加入進(jìn)去。如果寫入 cgroups.procs 的不是一個線程組 id,而是一個一般的線程 id,那會自動找到所對應(yīng)的線程組 id 加入進(jìn)去。進(jìn)程在加入一個控制組后,控制組所對應(yīng)的限制會即時生效。想知道一個進(jìn)程屬于哪些控制組,可以通過 cat /proc/<pid>/cgroup 查看。
要把進(jìn)程移出控制組,把 pid 寫入到根 cgroup 的 tasks 文件即可。因為每個進(jìn)程都屬于且只屬于一個 cgroup,加入到新的 cgroup 后,原有關(guān)系也就解除了。要刪除一個 cgroup,可以用 rmdir 刪除相應(yīng)目錄。不過在刪除前,必須先讓其中的進(jìn)程全部退出,對應(yīng)子系統(tǒng)的資源都已經(jīng)釋放,否則是無法刪除的。
前面都是通過文件系統(tǒng)訪問方式來操作 cgroups 的。實際上,也有一組命令行工具。
lssubsys -am 可以查看各子系統(tǒng)的掛載點,還有一組“cg”開頭的命令可以用來管理。其中 cgexec 可以用來直接在某些子系統(tǒng)中的指定控制組運(yùn)行一個程序。如 cgexec -g "cpu,blkio:/foo" bash 。其他的命令和具體的參數(shù)可以通過 man 來查看。
下面是個 bash 版的 cgexec,演示了 cgroups 的用法,也可以在不確定是否安裝命令行工具的情況下使用。
#!/bin/bash</p> <p># usage:
# ./cgexec.sh cpu:g1,memory:g2/g21 sleep 100</p> <p>blkio_dir="/sys/fs/cgroup/blkio"
memory_dir="/sys/fs/cgroup/memory"
cpuset_dir="/sys/fs/cgroup/cpuset"
perf_event_dir="/sys/fs/cgroup/perf_event"
freezer_dir="/sys/fs/cgroup/freezer"
net_cls_dir="/sys/fs/cgroup/net_cls"
cpuacct_dir="/sys/fs/cgroup/cpuacct"
cpu_dir="/sys/fs/cgroup/cpu"
hugetlb_dir="/sys/fs/cgroup/hugetlb"
devices_dir="/sys/fs/cgroup/devices"</p> <p>groups="$1"
shift</p> <p>IFS=',' g_arr=($groups)
for g in ${g_arr[@]}; do
IFS=':' g_info=($g)
if [ ${#g_info[@]} -ne 2 ]; then
echo "bad arg $g" >&2
continue
fi
g_name=${g_info[0]}
g_path=${g_info[1]}
if [ "$g_path" == "${g_path#/}" ]; then
g_path="/$g_path"
fi
echo $g_name $g_path
var="${g_name}_dir"
d=${!var}
if [ -z "$d" ]; then
echo "bad cg name $g_name" >&2
continue
fi
path="$wppm3vysvbp${g_path}"
if [ ! -d "$path" ]; then
echo "cg not exists" >&2
continue
fi
echo "$$" >"${path}/tasks"
done</p> <p>exec $*
cgroups 中的東西很多,本來打算只寫一篇的,后來覺著還是分成幾篇說得更明白些。之后還會寫一些具體使用的東西。
相關(guān)文章

集成系統(tǒng)級Claw模式! Deepin 官宣發(fā)布 25.1 版本
deepin操作系統(tǒng)發(fā)布了最新的 25.1 版本更新,該版本基于 deepin 25 正式版積累的多輪內(nèi)測成果,在 AI 能力、內(nèi)核版本、桌面環(huán)境、文件管理器以及系統(tǒng)安全等方面進(jìn)行了更新2026-04-13
又一代老硬件退場! Linux 內(nèi)核正式放棄Intel 486 CPU
在過去的幾十年間,CPU 的架構(gòu)已經(jīng)經(jīng)歷了飛速發(fā)展,x86 系列就是其中之一,而 i486 則屬于該系列中的一個,當(dāng)前,i486 的CPU處理器已經(jīng)夠老,從 Linux 7.1 開始將不再有對2026-04-09
趕緊收藏! 全網(wǎng)最全 Linux 命令總結(jié)
我把 Linux 中最常用、最實用、最常被問到的命令按照實際使用場景分類整理,方便你快速查閱和記憶,內(nèi)容覆蓋日常運(yùn)維、開發(fā)調(diào)試、性能分析、文件處理、網(wǎng)絡(luò)、安全、系統(tǒng)管2026-04-08
一分鐘內(nèi)檢查Linux服務(wù)器性能? 9個性能檢測常用的基本命令
今天我們來看看Linux系統(tǒng)中用于性能監(jiān)控的一系列命令,這些命令可以快速查看機(jī)器的負(fù)載情況,詳細(xì)請看下文介紹2026-03-18
從零基礎(chǔ)到精通! 適合高級用戶的15款Linux發(fā)行版推薦
Linux作為操作系統(tǒng)領(lǐng)域靈活性和可定制性的基石,提供了大量滿足不同用戶需求的發(fā)行版,今天分享適合高級用戶的15款Linux發(fā)行版2026-03-10
開箱即用? 這4個高手級Linux發(fā)行版遠(yuǎn)沒你想象的那么安全易用
如果你正在糾結(jié)用哪個發(fā)行版?零基礎(chǔ)新手別被“高端”“極客”“聲明式”這些詞沖昏頭腦,先用好用的,再慢慢進(jìn)階2026-03-10
這幾款SSH工具真的夠用了! Linux好用的ssh工具推薦
在Linux上使用SSH,您需要安裝一個SSH客戶端,今天整理找到的8 款 SSH / 終端工具,從免費(fèi)開源到企業(yè)級商用,從輕量化命令行到一站式工具箱,每款都做了介紹與對比,希望能2026-03-09
在Linux系統(tǒng)下有兩種用戶,即高級用戶root,普通用戶,高級用戶root可以在系統(tǒng)中做任何事情,普通用戶僅可在Linux系統(tǒng)中做有限的事情,下面我們就來看看切換方法2026-02-28
揭秘當(dāng)前登錄用戶的身份! Linux中使用logname命令的技巧
logname命令就是這樣一個簡單但強(qiáng)大的工具,它能幫助我們輕松獲取當(dāng)前登錄用戶的用戶名,今天,我們就來深入探索一下這個命令的工作原理、使用方法和最佳實踐2026-02-26
在 Linux 系統(tǒng)中,DNS 緩存是一種將域名和 IP 地址映射關(guān)系緩存在本地的機(jī)制,可以加快域名解析速度,并減輕 DNS 服務(wù)器的負(fù)載2026-02-26



