1.什么是Cgroup
Cgroups 是 control groups 的縮寫,是 Linux 內核提供的一種可以限制、記錄、隔離進程組(process groups)所使用的物理資源(如:cpu,memory,IO 等等)的機制。最初由 google 的工程師提出,后來被整合進 Linux 內核。Cgroups 也是 LXC 為實現虛擬化所使用的資源管理手段,可以說沒有 cgroups 就沒有 LXC。
2.Cgroup可以做什么
1.限制進程組可以使用的資源數量,限制進程最大使用的內存等。
2.進程組的優先級控制,比如為某個進程組分配特定的cpu share。
3.記錄進程組使用的資源數量,比如記錄某個進程CPU的使用時間。
4.進程組隔離,比如通過namespace以達到隔離的目的。
5.進程組控制,比如可以將進程組掛起或恢復。
3.Cgroup的模型
(1) 進程模型
在說Cgroup的模型之前,先回顧下進程模型,在linux系統上,所有的進程都有一個共同的父進程,叫做init進程,這個進程在內核啟動的時候開始執行,然后通過init進程啟動其他的進程,這些進程都是init的子進程。因為所有的進程都有一個共同的父進程。那么linux的進程模型就是一個單繼承層次的模型,或者稱之為樹狀模型。除此之外每一個linux進程但是除了init進程,都繼承了一些環境變量(例如PATH環境變量)。
(2) Cgroup模型
Cgroup其實和進程類似,Cgroup也是繼承體系,並且子Cgroup繼承其父Cgroup的某些屬性,兩者最基本的差別在於,進程是單繼承體系。而Cgroup可以存在多個不同的繼承體系(就是可以有多個單繼承體系,每個單繼承體系互不影響)。
4.Cgroup的一些概念
在Cgroup中有這樣四個概念,可以說理解了這四個概念,那么對於如何使用Cgroup:
Subsystems: 稱之為子系統,一個子系統就是一個資源控制器,比如cpu子系統就是控制cpu時間分配的一個控制器。
Hierarchies: 可以稱之為層次體系,也可以稱之為繼承體系,指的是Control Groups是按照層次體系的關系進行組織的。
Control Groups: 一組按照某種標准划分的進程。進程可以從一個Control Groups遷移到另外一個Control Groups中,同時Control Groups中的進程也會受到這個組的資源限制。
Tasks: 在Cgroups中,Tasks就是系統的一個進程。
5.Subsystems
在Red_Hat_Enterprise_Linux-6系列的linux中,默認提供了如下子系統,功能如下:
blkio: 這個子系統為塊設備設定輸入/輸出限制,比如物理設備(磁盤,固態硬盤,USB 等等) 。
cpu: 這個子系統使用調度程序提供對 CPU 的 cgroup 任務訪問。
cpuacct: 這個子系統自動生成 cgroup 中任務所使用的 CPU 報告。
cpuset: 這個子系統為 cgroup 中的任務分配獨立 CPU(在多核系統)和內存節點。
devices: 這個子系統可允許或者拒絕 cgroup 中的任務訪問設備。
freezer: 這個子系統掛起或者恢復 cgroup 中的任務。
memory: 這個子系統設定 cgroup 中任務使用的內存限制,並自動生成由那些任務使用的內存資源報告。
net_cls:這個子系統使用等級識別符(classid)標記網絡數據包,可允許 Linux 流量控制程序(tc)識別從具體 cgroup 中生成的數據包。
ns: 名稱空間子系統。
Ubuntu中的目錄是/sys/fs/cgroup, 但是高通的Android手機中這個目錄下是空的,存在於/dev目錄下,cgroup.rc指定了各個子系統的文件的路徑。
/dev/cgroup_info # strings cgroup.rc blkio:/dev/blkio cgroup2:/dev/cg2_bpf /dev/cpuctl cpuacct:/acct cpuset:/dev/cpuset //system-background、top-app也在這里面。 freezer:/dev/freezer memory:/dev/memcg schedtune:/dev/stune
也可以# mount | grep cgroup 來查看都掛載在哪里了。
6.Tasks文件不僅可以讀,還可以寫,你將一個進程的進程號寫入到某個cgroup目錄下的tasks里面,你就將這個進程加入了相應的cgroup。
7.cgroup文件系統和VFS文件系統類似,cgroups的定義如下
struct file_system_type cgroup_fs_type = { .name = "cgroup", .mount = cgroup_mount, .kill_sb = cgroup_kill_sb, //kill_sb釋放超級塊。 .fs_flags = FS_USERNS_MOUNT, };
8.Cgroup在kernel中的入口是:subsys_initcall(cgroup_sysfs_init); //msm-4.19\kernel\cgroup\cgroup.c
9.在cgroup文件系統中,對目錄下的文件進行操作時,會調用struct kernfs_ops cgroup_kf_ops 結構體中指向的函數。比如:對文件進行讀操作時,會調用 cgroup_file_read,在 cgroup_file_read 中,會根據需要調用該文件對應的 cftype 結構體定義的對應讀函數。
cgroups通過實現cgroup文件系統來為用戶提供管理cgroup的工具,而cgroup文件系統是基於Linux VFS實現的。相應地,cgroups為控制文件定義了相應的數據結構cftype,對其操作由cgroup文件系統定義的通過操作捕獲,再調用cftype定義的具體實現。
cgroup中的每一個文件的后台動作都是 使用以空結尾的struct cftype數組來定義對cgroup文件進行操作時的后台動作,如 static struct cftype swap_files[] 通過模塊初始化時執行cgroup_add_legacy_cftypes()添加到cgroup系統中,如 cgroup_add_legacy_cftypes(&memory_cgrp_subsys, memsw_cgroup_files)
10.Cgroup是將任意進程進行分組化管理的Linux內核功能。cgroup本身提供將進程進行分組化管理的功能和接口的基礎結構。而后的Android操作系統也就憑借着這個技術,為每個應用程序分配不同的cgroup,將每個程序進行隔離,達到了一個應用程序不會影響其他應用程序環境的目的。
11.概念
task:一個進程。
control group:控制族群,按照某種標准划分的進程組。
hierarchy:層級,control group可以形成樹形的結構,有父節點,子節點,每個節點都是一個control group,子節點繼承父節點的特定屬性。
subsystem:子系統。子系統就是資源控制器,每種子系統就是一個資源的分配器,比如cpu子系統是控制cpu時間分配的。
可以使用lssubsys -al來列出系統支持多少種子系統,和使用ls /sys/fs/cgroup/(ubuntu)來顯示已經掛載的子系統.
12.# mount | grep cgroup可以看掛載目錄,到對應的掛載目錄下,創建一個文件夾,就創建了一個control group了。
實驗1:
/dev/freezer # mkdir mytest /dev/freezer # ls mytest/ cgroup.clone_children cgroup.procs freezer.parent_freezing freezer.self_freezing freezer.state notify_on_release tasks yourtest /dev/freezer/mytest/ # echo $$ > tasks //當前shell進程就被設置進去了,之后更改屬性文件的值可以對其進行設置。
實驗2:
/dev/cpuset # mkdir mytest /dev/cpuset/mytest # echo "3" > cpus //使用CPU3 /dev/cpuset/mytest # ps -A | grep system_server 1772 /dev/cpuset/mytest # echo 1772 > tasks
上面操作就將system_server線程綁定到CPU3上了。
實驗3:
/dev/memcg # mkdir my_mem_ctl /dev/memcg/my_mem_ctl # ls cgroup.clone_children memory.kmem.failcnt memory.kmem.tcp.limit_in_bytes memory.max_usage_in_bytes memory.move_charge_at_immigrate memory.swappiness cgroup.event_control memory.kmem.limit_in_bytes memory.kmem.tcp.max_usage_in_bytes memory.memsw.failcnt memory.oom_control memory.usage_in_bytes cgroup.procs memory.kmem.max_usage_in_bytes memory.kmem.tcp.usage_in_bytes memory.memsw.limit_in_bytes memory.pressure_level memory.use_hierarchy memory.failcnt memory.kmem.slabinfo memory.kmem.usage_in_bytes memory.memsw.max_usage_in_bytes memory.soft_limit_in_bytes notify_on_release memory.force_empty memory.kmem.tcp.failcnt memory.limit_in_bytes memory.memsw.usage_in_bytes memory.stat tasks /dev/memcg/my_mem_ctl # echo $$ > tasks /dev/memcg/my_mem_ctl # echo 10M > memory.limit_in_bytes /dev/memcg/my_mem_ctl # cat memory.limit_in_bytes 10485760
上面是限制當前shell進程最大使用10M內存。
相關文件解釋:
memory.limit_in_bytes 顯示當前內存(進程內存+頁面內存)的使用量 memory.memsw.usage_in_bytes 顯示當前內存(進程內存+頁面內存)+交換區的使用量 memory.limit_in_bytes 設置、顯示內存(進程內存+頁面內存)使用量的限制值 memory.memsw.limit_in_bytes 設置、顯示內存(進程內存+頁面內存)+交換區使用量的限制值 memory.failcnt 顯示當前內存(進程內存+頁面內存)達到限制值的次數 memory.memsw.failcnt 顯示當前內存(進程內存+頁面內存)+交換區達到限制值的次數 memory.max_usage_in_bytes 顯示記錄的內存(進程內存+頁面內存)使用量的最大值 memory.memsw.max_usage_in_bytes 顯示記錄的內存(進程內存+頁面內存)+交換區使用量的最大值 memory.stat 輸出統計信息 memory.force_empty 強制釋放分配給分組的內存 memory.use_hierarchy 設置、顯示層次結構的使用 memory.swappiness 設置、顯示針對分組的swappiness(相當於sysctl的vm.swappiness)
參考:
Linux Cgroups詳解(三): https://www.cnblogs.com/lisperl/archive/2012/04/23/2466151.html?utm_medium=referral
003_Linux的Cgroup<實例詳解>: https://www.cnblogs.com/itcomputer/p/4634942.html
TODO:
Linux Cgroups詳解(一):https://www.cnblogs.com/lisperl/archive/2012/04/17/2453838.html
Linux Cgroups詳解(二):https://www.cnblogs.com/lisperl/archive/2012/04/18/2455027.html
LXC(Linux containers)快速入門:https://www.cnblogs.com/lisperl/archive/2012/04/15/2450183.html
Linux Cgroup 入門教程:cpuset:https://zhuanlan.zhihu.com/p/121588317