Linux 任务调度简介

吞吐 和 响应 是评估一个计算机系统性能的主要参数,比较典型的就是在IO系统中,Linux为了提高IO吞吐而将IO先缓存到内存中,这在本质上是牺牲了对某个IO的响应过程并以此来提高吞吐率。这种设计思路在Linux调度器的设计也可以看到,Linux并没有追求硬实时系统的高响应,而是在吞吐和响应之间取得一个平衡。

在Linux中,任务(或者说task_struct,由于Linux中进程和线程没有明显的界限,本文使用任务来描述一个可调度实例)一共有0-139个优先级,其中0-99是给RT 任务使用,100-140给普通任务使用,前者即实时调度策略,进一步又分为SCHED_FIFO和SCHED_RR,后者即普通任务,即SCHED_NORMAL。作为优先级更高的实时任务,SCHED_FIFO和SCHED_RR的任务一旦处于RUNNING(就绪)状态,就可以无条件抢占SCHED_NORMAL的CPU,而只要系统中有RT的任务在运行,SCHED_NORMAL就没有运行的机会。当然,即便是RT 任务,其也会有优先级高低的区别,对于不同优先级的RT任务,显然要严格按照高优先级优先运行的原则,而对于相同优先级的两个RT任务,如果使用SCHED_FIFO,就按照”先来后到”的顺序,只要先运行的任务没有放弃CPU,后来的任务不会被调度到; 如果使用SCHED_RR,同优先级的任务会”周期性”的都被执行到。

Linux中每一个SCHED_NORMAL任务都有一个nice值(-20~+19,缺省为0),这个nice值表示这个任务对于其他任务的”容忍”程度,nice值越大,表示这个任务越好说话,结果是这个任务占用的资源就会减少。早期的Linux通过动态的调整一个动态nice来平衡IO消耗型任务和CPU消耗型任务,不过如今这个工作已经被巧妙的CFS替代了

vruntime = pruntime/weight * delta

上图就是CFS的运作公式,pruntime表示当前任务实际运行的时间,weight是一个与nice值相关的权重,share是系统级/cgroup的调整参数。整个CFS基于红黑树实现进程调度。如下图所示:

上图的数字就是每个任务的vruntime,CFS在进行任务调度的时候,总是调度红黑树中vruntime最小的那个任务,由于IO消耗型的任务本身pruntime就比CPU消耗型的pruntime小,所以整体上IO消耗型的任务的vruntime更小,也就能够获得更多的被调度的机会,这样就能提高系统整体的吞吐。

Continue reading