2.6.4.3 带宽控制 - 挂起与解挂

当需要挂起一个cfs_rq时,系统调用函数 throttle_cfs_rq 来实现,挂起的意思就是不要让CFS再调度到该cfs_rq中的任何任务,也就是说,我们需要将整个cfs_rq从该CPU的rq中移除,实际上就是移除上层cfs_rq中指向当前cfs_rq的那个调度实体。整个流程我们可以参考下图:

这里系统将要挂起CPU0队列里面的 cfs_rq_2, 此时我们需要将 cfs_rq_1 中指向它的调度实体 SE_R1cfs_rq_1 中删除,而将 SE_R1 删除之后, cfs_rq_1 就是一个空队列了,这时又需要将指向它的调度实体 SE_R0cfs_rq_0 中删除。该过程需要一直沿着cfsrq的parent属性往上走,直到遇上不需要删除的cfs_rq为止,在上图中,该cfs_rq就是 cfs_rq_0. 整个挂起操作完成后,CPU0的队列示意图为:

当然挂起 cfs_rq 时,系统还需要更新所有受影响的 cfs_rq 中的对应字段。函数 throttle_cfs_rq 的实现如下:

最后 cfs_rq->throttled 被设置为1后,整个cfs_rq就被挂起了,被挂起的cfs_rq已经不在CPU的运行队列中,因此其中的任务就不会被调度到了。

上面是挂起操作,解挂的逻辑由函数 unthrottle_cfs_rq 完成,解挂是挂起的逆操作,代码结构几乎都可以对应上,主要就是将cfs_rq入队、更新对应se节点的信息、最后有必要的话调用 resched_curr 触发调度,感兴趣的读者可以自行阅读源码,这里不再深究。

Last updated

Was this helpful?