cgroup学习(八)——CPUSET子系统

来源:互联网 发布:功夫软件手机版 编辑:程序博客网 时间:2024/06/07 15:57

       对于CPUSET子系统我们主要解释对cpuset.cpus的操作。Read操作根据《cgroup学习(三)——伪文件》可以很容易的跟踪到代码,并解读,所以我们这里就不赘述,直接解释write及attach操作。首先我们看一下write操作的bt(使用systemtap见《使用systemtap获得内核函数的局部变量》):

sudo sh -c "echo 0-3 > cpuset.cpus"13219 (sh) cpuset_change_cpumask call trace: 0xffffffff810c2fc0 :cpuset_change_cpumask+0x0/0x20 [kernel] 0xffffffff810bfc6b :cgroup_scan_tasks+0x17b/0x270 [kernel] 0xffffffff810c4c2c :cpuset_write_resmask+0x17c/0x350 [kernel] 0xffffffff810be14f :cgroup_file_write+0x16f/0x320 [kernel] 0xffffffff81177e68 :vfs_write+0xb8/0x1a0 [kernel] 0xffffffff81178871 : sys_write+0x51/0x90[kernel] 0xffffffff8100b0f2 :system_call_fastpath+0x16/0x1b [kernel]

       注:cpuset在attach之前要求先设置cpus及mems的值,如果tasks里没有task的话,也不会调用到cpuset_change_cpumask,会在前面返回。
      因为代码被优化的原因所有在cpuset_write_resmask与cgroup_scan_tasks之间的update_cpumask及update_tasks_cpumask函数被优化掉了,其中前者主要完成参数的解析,验证(validate_change这个新的值必须是它的parent的子集,并且它的所有children还必须是新值的子集,以及exclusive的排除),然后才将新的值cpumask_copy(cs->cpus_allowed,trialcs->cpus_allowed);最后才更新它下面的所有进程的cpus_allowed(这里只是更新它这级的进程,并没有更新它下级的cgroup里面的进程,因为这些进程由这个子cgroup自己管理,它们也还是新值的一个子集)update_tasks_cpumask(该函数主要初始化一个cgroup_scanner结构,cgroup用它来遍历cgroup管理的每个进程,并定义对每个进程的test及process操作),然后就到了cgroup_scan_tasks函数,它就是扫描cgroup_scanner(即cgroup下的每个进程,使用cgroup_iter_{start,next,end}三个接口),这里使用了一个大顶堆(key为进程的create_time)来缓存需要更新的进程,这样做的原因是:保证在更新的过程中新创建的进程也会被更新到,所以这里有一个goto语句,直到heap->size=0才跳出,这样就可以减少在fork的代码里加锁。最后就是对heap里面的所有进程进行process处理cpuset_change_cpumask,该函数最终就把cgroup的cpus_allowed复制到task->cpus_allowed,并且判断这个进程是否从旧的CPU运行队列,迁移到新的CPUSET的运行队列(该过程由migrate_task完成)。
注:这里用到了cgroup最重要的几结构之间的转换,所以我们再画一张简易的图来表示一下:


图 cgroup 与task的转换

       第一行从cgroup查找CPUSET子系统对应的控制体实现类,subsys[]数组保存了该cgroup所属的所有子系统抽象类,最后通过container_of获得实现类(注:container_of是中task_group内存储了整个cgroup_subsys_state内容,而不是指向cgroup_subsys_state的指针);第二行是从cgroup控制体的CPUSET子系统实现类到它所属的cgroup再到该cgroup所管理的所有tasks,这里cgroup_iter->cg_link则保存cgroup的css_set list,而cgroup_iter->task则分别保存每次css_set的task list,即task会因为遍历的css_set而变化。(这些结构关系见《cgroup学习(二)——cgroup框架结构》)
     可以看出整个wirte过程,最终的目的就是在于更新该cgroup下的每个进程的cpus_allowed,并对已在运行队列里或正在运行的进程进行迁移。下面我们再来看一下cpuset的attach过程:
     通过《cgroup学习(三)——伪文件》表格的cpuset_subsys全局变量,我们可以找到CPUSET子系统的attach函数为:cpuset_attach,可以想象代码应该就是把新的cgroup的cpu_allowed赋到将要attach的task的cpu_allowed,然后该迁移的迁移,不过如果你看代码的话会发现其实不是这样的,多了一个guarantee_online_cpus函数,一开始百想不得其解,后来查了一下online cpu的概念才明白,原来linux可以把物理cpu直接禁止掉(修改/sys/devices/system/cpu下的所有core目录下的online文件,这也就是CPU的热插拔),所以这个函数的目的就是排除掉所有offline的cpu后的cpu_allowed。有了cpu_allowed进程在被创建时wake_up_new_task(继承自父进程的cpu_allowed)或者被唤醒时try_to_wake_up,都会通过select_task_rq(该函数后面调用CFS调度器里的select_task_rq_fair来选择cpu_allowed里的某一个cpu,可能是load最低的)来确定它应该被置于哪个CPU的运行队列及运行,一个进程在某一时刻只能存在于一个CPU的运行队列里。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 上个月忘记清卡怎么办 财务人员进入税务黑名单怎么办 社保本丢了怎么办 贷款车辆登记证书怎么办 发票薄丢了怎么办? 汽车发票丢了怎么办 税票弄丢了怎么办 交强险正本丢了怎么办 个体营业执照正本丢失怎么办 简易注销后税务怎么办 拒绝了日历邀请怎么办 老人走丢了怎么办 老人走丢找不到怎么办 没人给介绍对象怎么办 bate365账号被锁怎么办 qq号疑似被盗怎么办 不知道音乐名字怎么办 忘记支付宝登录怎么办 微信被老婆拉黑怎么办 微信群昵称改不了怎么办 微信号设置不了怎么办 修改微信号点不开怎么办 多屏设置失败怎么办 icould密码忘了怎么办 微信号换不了怎么办 微信号改不了怎么办? 无法设置微信号怎么办 公司改名后商标怎么办 公司名称变更后发票怎么办 被起诉公司企业变更怎么办 企业公章坏了怎么办 公司更名旧公章怎么办 手机证书不匹配怎么办 开庭对方不到场怎么办 被告公司名称写错怎么办 id卡丢失了怎么办 血小板高到1080怎么办 打印机处于错误状态怎么办 打印机晒鼓错误怎么办 打印机显示通讯错误怎么办 计算机名改不了怎么办