网上关于CFS 调度器的文章多如牛毛,没必要自己写。很多文章写的都非常好。
很多文章里,关键的技术点,都是一样的,只是各个文章说法不一样。
掌握了核心的,关键的,其他的,如果工作中需要的,可以详细了解。
这篇文章只是讲解一些 CFS的基础概念。“术” 的内容可以参考其他大佬的文章。
CFS 的基础概念其实就四个:
关于红黑树的内容可以参考之前的《【linux温故】红黑树》文章。这里就不说了。
Linux 在 2.6.24 之后,使用了新的调度程序 CFS。CFS即Completely Fair Scheduler,顾名思义,完全公平调度器。
很容易理解。
所有非实时可运行进程都以 虚拟运行时间 为键值用一棵红黑树进行维护,以完成更公平高效地调度所有任务。CFS 弃用 active/expired 数组和动态计算优先级,不再跟踪任务的睡眠时间和区别是否交互任务,而是在调度中采用基于时间计算键值的红黑树来选取下一个任务,根据所有任务占用 CPU 时间的状态来确定调度任务优先级。
首先要明白,CFS 调度,只是调度的一种。 CFS 调度针对的只是 普通进程。普通进程也有优先级啊,对,CFS 里面也有 权重(weight),权重越大的,当然得到的CPU 时间更多了,但是,这样不是和你说的 “完全” 公平概念不是不一样了吗?这玩意儿,妙就秒在这里,后面说。
首先,一个重要的基础概念是:“调度类”,这块摘抄一下吧:
也就是说,系统里面有很多调度类,有的调度类是给 实时进程用来做调度的,有的是给 普通进程做调度的。
每个进程在创建的时候,就会给他指定一种调度类,每一种调度类的优先级不一样,高优先级的调度类里面的进程,优先执行。
上面截图中解释了各个调度器。以及 linux 在选择下一个 task 的时候,是如何遍历调度器获取到的。
所以,最重要的一点是,,CFS 只是系统中的一种调度类而已,用来调度 普通进程的。
这是第二个重点的概念——权重。
这其实也是一个辅助概念,也是为最后 虚拟运行时间(virtual runtime)准备的。
简单说,就是一个进程在创建的时候,会有个 nice 值,表示这个进程的“谦让”程度 (-20 ~ 19),越大,表示越谦让。进程的权重,其实就是以 nice 为下标的数组中的对应项。
最后,这个 虚拟运行时间 才是我们最重要的概念。CFS 就是根据这个来选取下一个 task 的,每次从 红黑树 里面取 virtual runtime 最小的那一个对应的 task。(也就是红黑树的最左边的左节点的元素)。还是看下摘录的内容吧:
这里写的有点绕,其实 虚拟运行时间 的概念,很简单。
CFS 只是尽量保证每个进程的 虚拟运行时间 是相同的。之所以说是 “虚拟” ,是因为这个不是实际的运行时间。举个例子:
比如A进程从创建到目前,一共运行了 3600ms,如果A进程的nice 值是 0, 对应的 weight 就是 1024,那它的虚拟运行时间:3600* 1024/1024 = 3600ms ,就是实际运行的时间。但是如果B进程来了,他的运行时间也是 3600ms, 但是他的nice 值是 -10,weight = 9548,那它的虚拟运行时间是:3600 * 1024 / 9548 = 386ms!
也就是说,从 CFS 调度器看来,B 这个进程目前只运行了 386ms,然后他说,我应该给运行时间少的B多分配些时间运行!A就说了,你放屁,他和我一样运行了 3600ms 呢,你不是说公平吗?为啥偏爱他?CFS 说,你说的 3600ms 是 实际运行时间 我不看这个的,我所谓的公平,是指我保证所有的进程的 虚拟运行时间 是一样的。A:…(一万个草泥马浮现在脑海中)…
A 的nice 值(谦让值)太高导致的,这才是原罪。
从 CFS 的角度看,每个人的时钟速度是不一样的,有个进程的 时钟走的块,有的时钟走的慢。走的块的就是那种低优先级的,走的块的,就是那种高优先级的进程。
CFS,“完全公平”调度,这句话本身就是有歧义的,它实际上,非常不公平。本质上,谁的优先级高,它就还是偏爱谁。
CFS 之所以这么做,其实是有他的考虑的:就是能高优服务于交互式进程。提升用户交互的体验。
这么一想来,CFS 确实挺妙的。
这里就不分析了,可以参考下这篇:
https://www.cnblogs.com/TreeDream/p/8085133.html
上面的内容,基本都是参考别人的文章:
http://www.wowotech.net/process_management/447.html
https://zhuanlan.zhihu.com/p/372441187
https://blog.csdn.net/gatieme/article/details/52067748