cgroupはv1とv2という2つの実装(と言っていいのか?)があってそれらはkernel/cgroup.cで一つのコードベースにまとまっているのでコード読んでで混乱するなーというところで、誰得なめもを。
特に、4.1とかのカーネルだとv2のコードはまだ正式版となってないけどマージはされていて、DEVELsane_behaviorというオプションを使うことでv2の機能が使えるようになってます(参考:
Linux 3.16 から試せる cgroup の単一階層構造 (1) - TenForward)。今はv2がちゃんと入っているのでこのオプションは不要で、cgroupのマウント時にcgroup v2としてマウントするかどうかで切り分けできます。cgroup_mount()のis_v2がそれです。
2083 static struct dentry *cgroup_mount(struct file_system_type *fs_type, 2084 int flags, const char *unused_dev_name, 2085 void *data) 2086 { 2087 bool is_v2 = fs_type == &cgroup2_fs_type; 2088 struct super_block *pinned_sb = NULL; 2089 struct cgroup_namespace *ns = current->nsproxy->cgroup_ns; 2090 struct cgroup_subsys *ss; 2091 struct cgroup_root *root;
v1とv2は階層構造が違うんですが、どちらの構造を見せるかという判定には古めのカーネルならcgrp_dfl_root_visible変数、v2が正式に入ってからならcgrp_dfl_visible変数を使います。これはbool値を格納する変数で、trueならv2の構成を見せます。これらの変数の値を設定するのはcgroup_mount()です。
4.1の場合は以下のようにDEVELsane_behaviorオプションが設定されている場合にtrueをセットします。
1763 /* look for a matching existing root */ 1764 if (opts.flags & CGRP_ROOT_SANE_BEHAVIOR) { 1765 cgrp_dfl_root_visible = true; 1766 root = &cgrp_dfl_root; 1767 cgroup_get(&root->cgrp); 1768 ret = 0; 1769 goto out_unlock; 1770 }
4.10の場合はcgroup_mountの最初で設定したis_v2がtrueの場合(cgroup v2のファイルシステムをマウントする時)に設定します。
2113 if (is_v2) { 2114 if (data) { 2115 pr_err("cgroup2: unknown option \"%s\"\n", (char *)data); 2116 put_cgroup_ns(ns); 2117 return ERR_PTR(-EINVAL); 2118 } 2119 cgrp_dfl_visible = true; 2120 root = &cgrp_dfl_root; 2121 cgroup_get(&root->cgrp); 2122 goto out_mount; 2123 }
この変数を使っているところは1箇所だけで、proc_cgroup_show()です。この関数は何をやっているかというと/proc/
masami@saga:~$ cat /proc/self/cgroup 11:pids:/user.slice/user-1000.slice/user@1000.service 10:cpuset:/ 9:blkio:/ 8:net_cls,net_prio:/ 7:hugetlb:/ 6:perf_event:/ 5:cpu,cpuacct:/ 4:devices:/user.slice 3:freezer:/ 2:memory:/ 1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service
4.1も4.10カーネルもproc_cgroup_show()の以下のところで使ってます。
5111 if (root == &cgrp_dfl_root && !cgrp_dfl_root_visible) 5112 continue;
ここで出てくるcgrp_dfl_rootはstaticな変数です。
144 struct cgroup_root cgrp_dfl_root;
4.1の場合、cgroup_init_early()でinit_cgroup_root()を呼び出して最初の初期化しています。
4952 int __init cgroup_init_early(void) 4953 { 4954 static struct cgroup_sb_opts __initdata opts; 4955 struct cgroup_subsys *ss; 4956 int i; 4957 4958 init_cgroup_root(&cgrp_dfl_root, &opts); 4959 cgrp_dfl_root.cgrp.self.flags |= CSS_NO_REF;
init_cgroup_root()ではcgrp_dfl_rootのメンバ変数cgrpを対象に初期化してます。
1624 static void init_cgroup_root(struct cgroup_root *root, 1625 struct cgroup_sb_opts *opts) 1626 { 1627 struct cgroup *cgrp = &root->cgrp; 1628 1629 INIT_LIST_HEAD(&root->root_list); 1630 atomic_set(&root->nr_cgrps, 1); 1631 cgrp->root = root; 1632 init_cgroup_housekeeping(cgrp); 1633 idr_init(&root->cgroup_idr); 1634 1635 root->flags = opts->flags; 1636 if (opts->release_agent) 1637 strcpy(root->release_agent_path, opts->release_agent); 1638 if (opts->name) 1639 strcpy(root->name, opts->name); 1640 if (opts->cpuset_clone_children) 1641 set_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->cgrp.flags); 1642 }
次に、cgroup_init()でさらなる設定が入ります。ここではcgroup_setup_root()でcgroup本体(という言い方で良いのか?)を行っていて、cgroup_init()ではcgroupのサブシステムに関する設定を行っています。
( ´ー`)フゥー...
Linuxシステム[実践]入門 (Software Design plus)
- 作者: 沓名亮典
- 出版社/メーカー: 技術評論社
- 発売日: 2013/07/03
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (13件) を見る