CGROUP 是什麼呢?在 WIKI [1] 裡面簡直沒有幾行字, 要看懂不容易. 簡單地說, Linux 裡面有很多 process, 我們為了分而治之, 所以增加 group 的虛擬觀念. 每個 group 的 process 能夠使用的資源會有不同的限制. 比方說, 某些 process 可以用雙核, 某些 process 只能用單核. 某些 process 可以用 2GB DDR, 另一些 process 只能用 128MB.
我們可以在 console 下面 cat /proc/cgroups. 就會看見, 有 cpuset, cpu, cpuacct, memory, device, freezer, blkio, net_prio 等幾個 subsys_name. 而且他們各自有 hierachy, cgroups 的數目, 以及 enable 與否. 因為 Linux 底下的排版跑掉了, 所以除了第一列, 其他每一列都縮排.
以上面的 Android 系統為例 (Android 底下也是 Linux), 其中 cpuacct 這個 subsystem 就有 48 個 cgroup 之多. 什麼是 cpuacct 呢?它是指 CPU accouting control [2]. 假如 Linux 沒有生成 cpuacct 這個 cgroup, 我們可以用 command line 產生.
mount -t cgroup -ocpuacct none /sys/fs/cgroup/cpuacct
我用原生的 Linux 3.10 只看得到 memory 在 cgroup 的目錄下. 使用上面這個 mount 指令後, 我們可以在 /sys/fs/cgroup 底下看見 cpuacct. 如果這個 cgroup 已經成立, 我們就可以看到一些統計資料, 例如 cpuacct.stat, cpuacct.usage, cpuacct.usage_percpu…等等. [Note 1]
cat /sys/fs/cgroup/cpuacct.stat 可以看到 user 和 system 各自用了多少 cpu 時間, 例如:
user 100352
system 79817 (單位是 user_hz [3])
cat /sys/fs/cgroup/cpuact.usuage 得到
2096699156712 (單位是 ns)
cat /sys/fs/cgroup/cpuacct.usage_percpu 得到兩顆 CPU 的數字
1145393229564 952319269088
兩者相加就是 cpuacct.usage, 不過不是同一個時間, 所以數字又變大了. 光看統計數字沒有太大的幫助, 我們要怎麼使喚它呢?根據 [REF 4] 的說法, 至少有三種方法可以做到. 其中 command line 和 libcgroup 的方法都被它介紹過了, 還有一個 LXC 的方法, 在 [REF 5] 當中有說明.
我這邊就只整理 command line 的方法, 因為它最容易了解 cgroup 目錄階層的意義.我們可以手動在 /sys/fs/cgroup 底下操作.
[CASE 1] 如果要限制的是可以用幾核的 CPU, 比方說雙核中, 誰可以用兩顆 CPU, 誰只能用 (某) 一顆, 那麼要先設定第一核與第二核的定義.
cd /sys/fs/cgroup/cpuset
sudo mkdir first_core
echo 0 > /sys/fs/cgroup/cpuset/first_core/cpuset.cpus
sudo mkdir second_core
echo 1 > /sys/fs/cgroup/cpuset/second_core/cpuset.cpus
接下來開始分配, 假設有兩個 process, pid 分別為 1185 和 1195.
echo 1185 > /sys/fs/cgroup/cpuset/first_core/tasks
echo 1195 >/sys/fs/cgroup/cpuset/first_core/tasks
echo 1195 >/sys/fs/cgroup/cpuset/second_core/tasks
結果使得 pid 1195 可以用雙核, 而 1185 只能用單核.
[CASE 2] 若是要進一步把 pid 1185 的使用權種降得更低, 我們就要定義出比重.
cd /sys/fs/cgroup/cpu
sudo mkdir high
echo 2048 > /sys/fs/cgroup/cpu/high/cpu.shares
sudo mkdir low
echo 512 > /sys/fs/cgroup/cpu/low/cpu.shares
echo 1195 > /sys/fs/cgroup/cpu/high/tasks
這樣在同一顆 CPU 中, 1195 也可以拿到 1185 四倍的 CPU 時間.
[CASE 3] 如果要分配記憶體的用量, 首先要設一個會限制記憶體的 group, 例如 limited_memory.
cd /sys/fs/cgroup/memory
sudo mkdir limited_memory
將它的記憶體上限定為 128M Bytes
echo 128000000 > /sys/fs/cgroup/memory/limited_memory/memory.limit_in_bytes
然後江這個 pid 加到這個 group
echo 1185 > /sys/fs/cgroup/memory/limited_memory/tasks
如果它的記憶體用量硬是超過限制, 它會 swap 到 disk, 不會用 DDR. 不過看來這樣也會拖累效率就是了.
[ref]
1. 中文版 WIKI
cgroups(控制組)是Linux核心的一個功能,用來限制報告和分離一個行程組的資源(CPU、記憶體、磁碟輸入輸出等)。這個工作是由Google的工程師(主要是Paul Menage和Rohit Seth)在2006年以「process containers(行程容器)」的名字開始的;[1] 在2007年的晚些時候被重新命名為控制組(由於在核心中「容器」這個名詞的歧義引起的混亂)並被合併到2.6.24版的核心中去。[2] 自那以後,又添加了很多功能和控制器。
cgroups的一個設計標的是為不同的應用情況提供統一的介面,從控制單一行程(像nice)到系統級虛擬化(像opeNVZ,Linux-VServer,LXC)。cgroups提供:
- 資源限制:組可以被設定不超過設定的記憶體限制;這也包括虛擬記憶體。[3] 原來的分頁機制是在Linux研討會的Containers: Challenges with the memory resource controller and its performance報告中提出的。[4]
- 優先化:一些組可能會得到大量的CPU[5] 或磁碟輸入輸出通量。[6]
- 報告:用來衡量系統確實把多少資源用到適合的目的上。[7]
- 分離:為組分離名稱空間,這樣一個組不會看到另一個組的行程、網路連線和檔案。[2]
- 控制:凍結組或檢查點和重新開機動。[7]
3. 3.3. cpuacct
[Note 1] 同理, 我也可以 mount -t cgroup -ocpuset none /sys/fs/cgroup/cpuset, 不過需要手動在 cgroup 底下建這些目錄才 mount 得到. 我用 Linux 3.10, 最初 cgroup 底下只有 memory 一個目錄而已.
建完新目錄之後, 底下就會自動繼承出一大堆子目錄. 例如 cpuset 底下的 first_core 就會自動有 cpuset.cpus.