在正式介绍进程调度的细节前需要对一些概念作出介绍:
进程调度的职责:负责决定在什么时间,将那个进程投入使用,以及进程运行的时间。从而达到系统资源最大限度发挥,多进程并发执行的效果。
1、linux内核中进程的状态:
1).就绪和运行状态:TASK_RUNNING:此时程序已经被挂入运行队列,处于准备运行的状态,一旦获得处理器的使用权限,即可进入运行的状态,在进入运行运行状态之后,状态标志位不会发生变化,但linux中会把一个专门指向当前运行任务的指针current指向它以表示是一个正在运行的进程;
2).可中断等待状态:TASK_INTERRUPTIBL:进程申请未获得他所申请的资源而处于等待的状态,一旦资源的申请完成或者有唤醒的信号,会立即结束等待进入就绪状态;
3).不可中断等待状态:TASK_UNINTERRUPTIBL:进程处于等待资源的状态,一旦资源有效就立即进入就绪状态,但是此状态不能被其他的信号或者中断唤醒,只有申请的资源有效时才能被唤醒。 内核进程的常见方式,在内核中很多的进程是不能被打断的。
4).停止状态:TACK_STOPPED:进程收到SIGSTOP信号后就由运行状态进入这个停止状态,当收到SIGCONT信号时恢复运行状态;(暂停状态、挂起状态);
5).终止状态(僵死状态):TASK_SEAD:进程由于某种原因而终止运行,进程除task_struct和少数资源以外的所有资源均被回收,并且系统将不再对其予以理睬。
进程间的状态图如下:
2、linux的调度时机
①进程状态转换的时刻,如进程中止、进程睡眠等;
②可运行队列中新增加一个进程时;
③当前进程的时间片用完时;
④进程从系统调用返回用户态时;
⑤内核处理完中断后,进程返回用户态时。
说到进程调度就不得不说说多任务系统,在单任务系统中处理器仅能单一的运行一个进程,所以也就不需要进行进程间的调度。而多任务系统能同时并发执行多个进程的操作系统。在单个处理器的机器中,由于多任务系统的调度会产生多个进程同时并发执行的幻觉。
3、多任务系统
对于多任务系统可以划分为两类:抢占式多任务系统、非抢占式多任务系统。
抢占式多任务系统:在这种系统中由系统的进程调度系统负责决定进程的开始、停止,而一个进程在自己的时间片(每一个进程在被抢占之前,调度系统为其预先分配一个供其运行的处理器时间段,这个预设的处理器时间段就是时间片)使用完毕之后被强制挂起使得另一个进程被调度执行的过程叫做抢占。这也是linux采用的任务处理方式。
非抢占多任务系统:进程一直执行,直到进程自己结束自己的任务,下一个进程才得以执行。进程自动挂起自己的操作称为让步。显然这种系统存在很大的弊端。
下面开始我们真正的主题:linux进程调度的调度策略。
调度策略的任务:决定调度程序在何时让什么进程运行;优化进程使用处理器的时间。
4、io消耗型、处理器消耗型:
从进程的调度策略角度来看,进程可以分为:io消耗型、处理器消耗型。
io消耗型:进程在运行的时间内,大部分的时间用于提交io请求、等待io请求,而其真正运行的时间只是很少的一部分。在等待的更多的io请求时最后总会阻塞。 最典型的就是图形化界面进程,大部分的时间用于等待键盘、鼠标的输入等用户交互操作,而真正用于处理交互操作数据的时间少之又少。
处理器消耗型:大部分的时间用于执行代码,除非被抢占,否则会一直的执行下去。对于此类的进程调度策略往往是降低对其的调度频率,延长其处理时间。 最典型的就是大量数字计算的程序,例如MATLAB。
5、进程的优先级
在进程的调度算法中最基本,也是使用最多的就是基于优先级的调度。而其中最具代表的就是多级反馈队列算法:根据进程的紧急程度、进程的价值、以及其对处理器时间的需求来设置进程的优先级,优先级高的先执行,同等优先级的进程轮方式调度执行。
linux中使用两种不同的优先级范围来影响进程的调度,分别是:nice优先级和实时优先级。这两种优先级是完全互不相交的范畴。
nice优先级:范围是-20~19,默认值是0,越大优先级越小。在linux系统中为了实现更大的公平性,nice值代表着分配给进程的时间片的比例(这点十分关键,在后面有分析原因)。而在其他的系统nice值直接与为进程分配的时间片大小成反比,直接代表分配给进程的时间片绝对值。 ps -el 查看系统中的进程列表,NI表示的就是进程对应的nice值。
实时优先级:范围0~90,越高的实时优先级数值对应越高的进程优先级。任何的实时进程的优先级都高于普通进程。
6、时间片
时间片:一个数值,用于表明进程在被抢占之前所能持续运行的时间。调度策略负责规定一个默认的时间片。过长的时间片会给用户带来明显的卡顿感觉,影响用户的交互体验;而太短的时间片会导致处理器花费在在进程间切换的时间比重增大,处理器的利用率降低。此时io消耗型和处理器消耗型进程的矛盾也体现了出来,io消耗型偏向于更小的时间片以达到更快的处理,更少的等待时间,相反处理器消耗型偏向于更长的时间片以争取更多的运行时间,更高的处理器利用率(处理消耗型进程的进程间切换耗费的资源很多)。
时间片的设置:linux系统与其他的很多系统不同,在其他大部分的系统将默认的时间片设置为10ms,但在linux系统中的CFS调度器(进程间调度器)并不为每个进程设置具体的时间片,而是将处理器的使用比例划分给进程,这样每个进程的占有的处理时间也与处理器的能力密切相关。同时这个比例还会受到nice值的影响,nice越高的进程优先级越高,能获得更高的处理器使用比例。
在linux中使用CFS调度器,其抢占时机取决于新的进程消耗了多少处理器的使用比,如果消耗的处理器使用比小于当前进程则新的进程立刻投入运行,抢占当前进程。