cgroups簡介
cgroups(control groups)包含三個組件,分別爲cgroup、hierarchy,以及subsystem。
cgroup
cgroup是對進程分組管理的一種機制,cgroups中的資源控制都以cgroup爲單位實現。cgroup表示按某種資源控制標準劃分而成的任務組,包含一個或多個子系統。一個任務可以加入某個cgroup,也可以從某個cgroup遷移到另外一個cgroup。
subsystem
subsystem 是一組資源控制的模塊,主要包含cpuset, cpu, cpuacct, blkio, memory, devices, freezer, net_cls, net_prio, perf_event, hugetlb, pids。具體介紹如下:
cpuset 在多核機器上設置cgroup 中進程可以使用的CPU 和內存
cpu 設置cgroup 中進程的CPU 被調度的策略
cpuacct 可以統計cgroup 中進程的CPU 佔用
blkio 設置對塊設備(比如硬盤)輸入輸出的訪問控制
memory 用於控制cgroup 中進程的內存佔用
devices 控制cgroup 中進程對設備的訪問
freezer 用於掛起和恢復cgroup 中的進程
net_cls 用於將cgroup 中進程產生的網絡包分類,以便Linux 的tc (traffic con位oller)可以根據分類區分出來自某個cgroup 的包並做限流或監控
net_prio 設置cgroup 中進程產生的網絡流量的優先級
perf_event 增加了對每group的監測跟蹤的能力,即可以監測屬於某個特定的group的所有線程以及運行在特定CPU上的線程
hugetlb 限制HugeTLB(huge translation lookaside buffer)的使用,TLB是MMU中的一塊高速緩存(也是一種cache,是CPU內核和物理內存之間的cache),它緩存最近查找過的VA對應的頁表項
pids 限制cgroup及其所有子孫cgroup裏面能創建的總的task數量
查看kernel支持的subsystem可以使用lssubsys
命令:
root@xftony:~# lssubsys -a
cpuset
cpu,cpuacct
blkio
memory
devices
freezer
net_cls,net_prio
perf_event
hugetlb
pids
同時可以在/sys/fs/cgroup/memory
目錄下可以查看:
root@xftony:/sys/fs/cgroup# ls
blkio cpu,cpuacct freezer net_cls perf_event
cpu cpuset hugetlb net_cls,net_prio pids
cpuacct devices memory net_prio systemd
hierarchy
把一組cgroup串成一個樹狀的結構,一個這樣的樹便是一個hierarchy。一個系統可以有多個hierarchy。通過這種樹狀結構,cgroups可以做到繼承。
下面這個例子就是一顆hierarchy, 其中c0是其根節點,c1、c2是c0的子節點,會繼承c0的限制,c1、c2可以在cgroup-test的基礎上定製特殊的資源限制條件。
root@xftony:~/test/c0# tree
.
├── c1
│ ├── cgroup.clone_children
│ ├── cgroup.procs
│ ├── notify_on_release
│ └── tasks
├── c2
│ ├── cgroup.clone_children
│ ├── cgroup.procs
│ ├── notify_on_release
│ └── tasks
├── cgroup.clone_children
├── cgroup.procs
├── cgroup.sane_behavior
├── notify_on_release
├── release_agent
└── tasks
cgroup、subsystem、hierarchy三者關係
1、一個subsystem只能附加到一個hierarchy上面;
2、一個hierarcy可以附加多個subsystem;
3、一個進程可以作爲多個cgroup的成員,但是這些cgroup必須不在同一個hierarchy上。在不同的hierarchy上可以擁有多個subsystem,進行多個條件限制;
4、一個進程fork出來的子進程開始時一定跟父進程在同一個cgroup中,後面可以根據需要將其移動到其他cgroup中;
5、創建好一個hierarchy後,所有的進程都會加入這個hierarchy的根結點(暫時覺得很奇怪==);
6、cgroups裏面的task內放置遵循該cgroup的進行id(pid),同一個hierarchy裏面,只能有一個。
cgroups測試:
cgroup的創建
創建一個掛載點,即創建一個文件夾,存放cgroup文件:
#mkdir cgroup-test
掛載一個hierachy,不關聯任何subsystem
#mount -t cgroup -o none,name=cgroup-root cgroup-root1 ./cgroup-test
//此時使用mount查看可以看到
root@pgw-dev-4:~/test/cgroup-test# mount |grep cgroup
cgroup-root1 on /root/test/cgroup-test type cgroup (rw,relatime,name=cgroup-root)
cgroup-test 目錄下會生成一組默認文件:
root@pgw-dev-4:~/test/cgroup-test# ls
cgroup.clone_children cgroup.procs cgroup.sane_behavior notify_on_release release_agent tasks
cgroup.procs
內爲樹中當前節點的所有進程ID;
tasks
文件內存放所有隸屬於跟cgroup節點的線程ID;
cgroup.sane_behavior
標記sane_behavior
是否生效,”Linux 3.16-rc2”後,該flag在non-default模式下已刪除;
notify_on release
和release_agent
會一起使用,notify_on release
標識當這個cgroup最後一個進程退出的時候是否執行了release_agent;
release_agent
是一個路徑,通常用作進程退出之後自動清理掉不再使用的cgroup。
查看cgroup.procs
和tasks
,我們可以看到系統中正在運行的進程和線程ID;
此時我們在創建一個新的hierachy c0
#mount -t cgroup -o cpuset,name=c0-cpuset c0 ./c0
所有的cgroup.procs
和tasks
也都會加到c0內的cgroup.procs
和tasks
。
subsystem的掛載
subsystem默認的mount的位置是在/sys/fs/cgroup/XXX
,可以使用lssubsys -am
命令查看。因爲一個subsystem只能附加到一個hierarchy上面,因此在測試前,我們想將一些subsustem從原位置上umount,此處我們以memory和cpuset爲例:
umount subsystem
umount /sys/fs/cgroup/cpuset/cpuset
mount subsystem
然後我們在創建c0, c0上不綁subsustem,然後在c0下創建c1, c1上mount cpuset子系統:
mkdir c0
mount -t cgroup -o none c0 ./c0
mkdir c1; cd c1
mount -t cgroup -o cpuset c0 ./c1
其得到的cgroup結構爲:
root@xftony:~/test# tree -L 3
.
└── c0
├── c1
│ ├── cgroup.clone_children
│ ├── cgroup.procs
│ ├── cgroup.sane_behavior
│ ├── cpuset.cpu_exclusive
│ ├── cpuset.cpus
│ ├── cpuset.effective_cpus
│ ├── cpuset.effective_mems
│ ├── cpuset.mem_exclusive
│ ├── cpuset.mem_hardwall
│ ├── cpuset.memory_migrate
│ ├── cpuset.memory_pressure
│ ├── cpuset.memory_pressure_enabled
│ ├── cpuset.memory_spread_page
│ ├── cpuset.memory_spread_slab
│ ├── cpuset.mems
│ ├── cpuset.sched_load_balance
│ ├── cpuset.sched_relax_domain_level
│ ├── notify_on_release
│ ├── release_agent
│ └── tasks
├── cgroup.clone_children
├── cgroup.procs
├── cgroup.sane_behavior
├── notify_on_release
├── release_agent
└── tasks
cgroup的使用
在c1目錄下創建測試目錄cputest
,然後設置cpu
限制。
cd c1
mkdir cputest; cd cputest
//僅允許使用 Cpu1
echo 1 > cpuset.cpus
啓動測試程序:
root@xftony:~/test# cat test.sh
touch /root/test/my.lock
lock_file=/root/test/my.lock
x=0
while [ -f $lock_file ];do
x=$x+1
done;
root@xftony:~/test#./test.sh
此時top查看其內存cpu佔用情況:
%Cpu0 : 75.0 us, 23.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 2.0 st
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
32664 root 20 0 23268 5828 2228 R 99.3 0.1 1:13.56 bash
我們將該腳本的pid:32664
加入到cputest
的tasks
下:
root@xftony:~/test/c0/c1/cputest#echo 32664 > tasks
此時在top中,該進程已經遷移到Cpu1
中:
%Cpu0 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 77.1 us, 22.9 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
32664 root 20 0 25060 7636 2228 R 100.0 0.1 5:09.95 bash
top中cpu各參數含義:
us 用戶空間佔用CPU百分比
sy 內核空間佔用CPU百分比
ni 用戶進程空間內改變過優先級的進程佔用CPU百分比
id 空閒CPU百分比
wa 等待輸入輸出的CPU時間百分比
hi 硬件中斷
si 軟件中斷
st: 實時