linux 进程调度 [分章]算法

来源:互联网 发布:优化环境工作自查报告 编辑:程序博客网 时间:2024/04/29 19:34

首先,从不同的角度,可以对运行中的进程分类。

如,从资源耗损的角度,可以分为I/O受限(频繁使用I/O设备)和CPU受限(需要大量的CPU计算)。

又如,从运行模式上,可以分为交互式进程(需要大量的时间等待用户的键盘和鼠标指令,同时进程需要在指令到达后被尽快唤醒),批处理进程(如编译程序,数据库等),实时进程(如软件codec,编码对实时性要求很高)。

还如,从在内核中被调度的方式上,可以分为FIFO(实时进程),RR(时间片轮转实时进程), NORMAL(普通进程)

然后,再来了解一下进程在声明周期中的状态。

1,可运行状态(TASK_RUNING)

进程要么是在CPU上执行,要么准备执行,所以实际上这个状态包括运行中(RUNNING)和准备好了(READY)两个状态

2,可中断的等待状态(TASK_INTERRUPTIBLE)

进程被挂起,直到某个条件或者时间满足(硬件中断/进程等待资源被释放/传递给进程一个信号)变为TASK-RUNNING。

3,不可中断的等待状态(TASK-UNINTERRUPTIBLE)

与2类似,不同的是信号无法迁移其状态,少用。

4,暂停状态(TASK_STOPPED)

进程在收到SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU信号后,进入此状态,执行被暂停。

5,跟踪状态(TASK_TRACED)

进程的执行由debugger暂停。

6,僵尸状态(EXIT_ZOMBIT)

进程执行被终止,但是资源还未被父亲(如果父亲已经推出,则由init进程)回收。

7,僵死撤销状态(EXIT_DEAD)

对于已经终止的进程,资源已经被父亲或init回收,进程已经被删除,为防止其他执行线程回收此进程,故设置此状态。

具体的状态切换见下图:


进程调度:

1,Linux的进程调度基于分时技术:多个进程以“时间多路复用”方式运行,也就是我们常说的时间片。时间片的长短采取折衷机制,即尽量减少对系统响应的影响,同时又降低进程切换的开销。

2,进程的优先级是动态的,尽管确实有静态优先级的存在。

3,linux的进程是抢占式的,如果进入TASK_RUNNING状态且优先级比当前运行的进程高,当前进程被终止,将CPU交给更高优先级的进程。同时自己的TIF_NEED_RESCHED被设置,以便时钟中断处理程序终止时调度程序被正常调用。需要指出的是被抢走CPU的进程仍然是TASK_RUNNING状态,知识出于READY的子状态。


调度算法:

一个调度算法机制对于计算机的运行时状态影响是非常大的。

在早期的内核版本上,每次进程切换时,内核扫描可运行的task链表,计算优先级,然后选择最佳task运行,如果处于可运行的task太多,这个算法耗费的时间就很多,因为这个task选择的复杂度是O(n)。

在2.6内核上,对于O(n)task选择算法做了重大改进,基于runqueue,每个cpu都有自己的运行队列,这个队列里面有组织好的task结构,可以再常数时间O(1)内找个下一个得到cpu执行权限的task。

在2.6.23版本之后,O(1)被CFS(Completely Fire Scheduler),这个调度器的复杂度为O(logn)。

在文章的最开头,便介绍了从调度类型上讲,进程可分为实时(又包括全实时和基于时间片的实时进程)和非实时进程。

linux虽然不是标准的RTOS,但是也有实时性的需要(比如,个人曾经参与过一个系统的开发,一个ARM双核的处理器分别跑的一个RTOS t-kernel和linux,经常会出现linux数据发送调度不上,导致RTOS饿死的现象,后来改为FIFO的就好多了),因此内核对实时性进程也有支持。

1,普通进程的调度。

每个普通进程都有自己的静态优先级(从100最高到139最低,缺省120),这是它被调度器评估是否能暂用CPU的一个指标,但是,请注意,不是全部指标。

与这个静态优先级和另外一个叫做nice(-20到19)值的玩意儿对应,可以通过修改task的nice,可以改变其优先级,进而该表其拿到的时间片。

进程基本时间片与优先级的关系如下:

静态优先级大于等于120:时间片 = (140 - 静态优先级)* 5

静态优先级小于120:       时间片 = (140 - 静态优先级)* 20

从上面公式可以看到静态优先级越小,拿到的时间片越多。

优先级、nice值、基本时间片和睡眠时间极限值对应关系见下表

说明静态优先级nice基本时间片最大睡眠时间最高静态优先级100-20800ms299ms高静态优先级110-10600ms499ms默认静态优先级1200100ms799ms低静态优先级1301050ms999ms最低静态优先级139195ms1199ms

这里要插一句,为什么时间片会影响运行呢,因为调度器将进程分为活动进程和过期进程。

为了防止低优先级得不到cpu,在当一个进程用完所有时间片后,他就从活动变成了过期,过期进程不参与调度,从而让低优先级的任务也得到调度。

上面提到了“静态优先级只是能否被调度上的一个指标,而不是全部”,那剩下的是什么呢?

NORMAL进程除了静态优先级之外,还有动态优先级,其范围同样是100(最高)到139(最低)。

静态优先级是用来基于task能获得的时间片,而动态优先级是值调度器在选择进程是直接使用的依据。

在介绍动态优先级的计算之前,先来了解一个叫做bonus的数(年终了,看见这个单词总是有点激动啊)

bonus是范围从0到10的值,以5为分割线,分别表示奖励(大于)或者惩罚(大于),这个奖励惩罚来源于该task过去的运行状态,即其睡眠时间。

动态优先级计算法公式:

动态优先级 = Max(100, min(静态优先级 - bonus + 5,139))

2,实时进程的调度

实时进程也有一个优先级,叫做实时优先级(从1到99,1最高,99最低)。有更高优先级的实时task在执行时,并且严格按照优先级来执行,所以,低优先级是无法执行的,实时进程一直是活动进程。

实时进程只有在以下三种情况让出CPU:

a,有更好优先级的实时进程产生或者激活。

b,自己shced_yield让出cpu

c,进程退出或被杀。

d,执行了阻塞操作进入睡眠等待唤醒

e,如果是带时间片的实时,时间片用完。

PS:对于带时间片的实时进程,即拥有实时优先级,又拥有静态优先级,修改nice值只会改变其拥有的时间片大小,不修改其实时优先级。

 


0 0
原创粉丝点击