attach task
该过程对应于我们上面的实例操作的:echo 512 > tasks的过程,其实质就是先对cgroup下tasks文件进行写操作,建立该进程新的css_set与所有管理它的cgroup的关系;然后再根据各个子系统自己的attach函数进行attach操作。在这里我们先介绍第一个过程,第二个过程在各个子系统中介绍。先看一下bt:
- 12530 (sh) cpu_cgroup_attach call trace:
- 0xffffffff81065a20 :cpu_cgroup_attach+0x0/0x60 [kernel]
- 0xffffffff810c1d3e :cgroup_attach_task+0x26e/0x620 [kernel]
- 0xffffffff810c214c :cgroup_tasks_write+0x5c/0xf0 [kernel]
- 0xffffffff810be29a :cgroup_file_write+0x2ba/0x320 [kernel]
- 0xffffffff81177e68 :vfs_write+0xb8/0x1a0 [kernel]
- 0xffffffff81178871 : sys_write+0x51/0x90[kernel]
- 0xffffffff8100b0f2 :system_call_fastpath+0x16/0x1b [kernel]
- if (css == &init_css_set) {
- res = &root->top_cgroup;
- } else {
- struct cg_cgroup_link *link;
- /*因为css_set会被多个cgroup管理,但是这些cgroup都是属于不同的hierarchy,所以当遍历到一个cgroup它的root等于当前的hierarchy,那么这个cgroup就是该task在该hierarchy下当前所属的cgroup*/
- list_for_each_entry(link, &css->cg_links, cg_link_list) {
- struct cgroup *c = link->cgrp;
- if (c->root == root) {
- res = c;
- break;
- }
- }
- }
如果要attach的新的cgroup与该task之前在该 hierarchy 所属的cgroup一样则直接返回;否则,先判断该task是否可以在所有subsys上can_attach,然后通过find_css_set查找一个已经存在的css_set或者创建一个新的:首先通过find_existing_css_set查找是否有一个可用的css_set( 从css_set_table哈希表中查出与该task旧的css_set所属的子系统+新的子系统相同的css_set链表,然后遍历这个链表的每个node与旧的css_set所关联的cgroup是否一样(compare_css_sets,除去新的将要attach的cgroup),其实质就是查找是否存在这样一个css_set:该task旧的css_set的所有cgroup去掉它在当前hierarchy下的cgroup,加上新的它即将加入的cgroup,组成的css_set ),有则直接返回;否则,创建一个新的css_set,并且建立新的css_set(res)与该task之前旧的css_set(oldcg)的所有关联的cgroup(其实也是root_count个 hierarchy ,因为在每个hierarchy下都有一个cgroup与之相关,除去它之前所属的cgroup)的关系,再把该新的css_set加入到哈希表hlist。最后再调用每个子系统的attach,即第二个过程。
下面的图3(来自http://blog.chinaunix.net/uid-20543183-id-1930840.html),展现了我们前面介绍的三个过程mount,mkdir,attach:
图3 cgroup mount,mkdir及attach关系图