在多道程序设计系统时,通常就会有多个进程或线程同时竞争CPU。只要有两个或更多的进程处于就绪状态,就会发生这种情形。

如果只有一个CPU可用,那么就必须选择下一个要运行的进程。可以想象在多核的情况下,进程数小于核数时,根本就无须竞争,直接分配给空闲CPU即可。

这一部分选择的工作叫做调度程序。当然用来选择的算法就叫做调度算法。

进程与线程的调度区别和会产生的问题会在下面一一道来。内核态下的线程管理,和线程属于哪个进程没有关系,这个点要关注一下。

早期的以磁带上的卡片为输入的批处理系统时代,调度算法很简单,依次执行磁带上的每一个作业。

然后是多道程序设计系统,经常有多个用户等候服务,大型机上使用批处理(假设只是运行单个程序的请求)和分时服务结合使用,系统需要分辨下一个是需要处理的作业还是分时交互的用户。 

CPU被交互用户和作业共同竞争着,那么它自然是稀缺的资源。这时候为了去提高性能和用户满意度,新的调度算法开始酝酿。

个人计算机开发发展,在初期,个人计算机只有一个活动进程,调度程序基本不用工作。唯一的候选程序就是文字处理软件,当然同初期的PC对比,我们现在耗时更多的是I/O的等待,现代CPU处理速度极快,而相反用户键入键盘或点击鼠标的速度相对更慢。

但是当网络服务器出现,就出现了多个进程经常去竞争CPU

到此,为了选取正确的进程运行,调度程序还要考虑CPU的利用率,进程间切换的代价实在是有点大。

切换表现如下

1.从用户态切换到内核态,类似于访管指令。

2.保存当前进程的状态(进程表中存储的寄存器的值)、许多系统还要保存内存映像(如页表中的内存访问位)。

3.运行调度算法,选定新进程。

4.将新进程的内存映像重新装入MMU。

5.新进程开始运行。

你以为这样就结束了吗?其实在切换到这个进程中,整个内存cache失效,缓存强迫在内核中装入一次在离开内核又装入一次

这样看出来单位时间内切换进程的次数过多,会十分的耗时。

一、进程行为

几乎所有进程的I/O请求或计算都是交替突发的。

java 调度线程和工作线程 线程调度和进程调度_调度算法

a图是计算密集型,b图是I/O密集型。现在基本是I/O密集型,因为CPU已经发展的足够快,I/O运行的速度远远跟不上CPU处理速度,而磁盘却赶不上这个发展速度。

二、何时调度

1.创建一个新进程之后,需要决定运行父进程还是运行子进程。

正常决策问题,可以任意决定,调度程序合法选择即可。

2.在一个进程退出时必须做出调度决策。

必须从就绪队列上选择另一个进程。如果没有,就运行一个系统的空闲进程。

3.当一个进程阻塞在I/O和信号量上 或 由于 其他原因 阻塞,必须选另一个进程运行。

4.发生I/O中断时,需要作出调度决策。

如中断来自I/O设备,该设备现在完成了工作,某些被阻塞等待该I/O的进程就成为就绪进程,这时是否调度,或是让中断发生时的程序继续运行,就取决于调度程序。

若让硬件时钟在固定频率里周期性中断,可以在每个时钟中断时做出调度决策。

可以分为非抢占式、抢占式两类调度算法。

前者非抢占式调度算法挑选一个进程,让该进程运行直至被堵塞,或者直到该进程自动释放CPU,绝不会被强制挂起。

即在时钟中断时不进行调度,在处理完时钟中断后,如果没有更高优先级的进程等待到时,则被中断的进程会继续执行。

后者抢占式调度算法挑选一个进程,并让该进程挑选另一个进程运行在某个固定时段的最大值。如果该时段结束,该进程还在运行,则挂起,调度程序此时挑选另一个进程运行(存在就绪进程)。这时候的时间中断发生在时间间隔的末端,方便把CPU控制返回给调度程序。

没有可用的时钟就只能用非抢占式。

三、调度算法分类

批处理----非抢占式普及

交互式----抢占式普及

实时----抢占和非抢占结合

四、调度算法的目标

java 调度线程和工作线程 线程调度和进程调度_java 调度线程和工作线程_02

 

批处理中的调度算法(当然有些算法也可以用在别的系统中):

1.先来先服务(FCFS)

属于非抢占式,进程按照他们请求的CPU顺序使用CPU。用一个就绪队列来管理。

该算法的缺点:

对长作业有利(适合于CPU繁忙型,不利于I/O繁忙型)。I/O处理时间很长,而这时CPU处于无事可做等待I/0的状态,而后面的CPU请求也无法再去接受。

2.最短作业优先(SJF)

也属于非抢占式,之所以叫最短,肯定运行时间是可以预测的。

长期运行,对长作业不公平

3.最短剩余时间优先

属于SJF的抢占式版本,如果新的进程比当前运行进程需要更少的时间,当前进程就被挂起。可以让后面的新的短作业获得良好的服务。

交互式系统中的调度

1.轮转调度

时间片轮转,就不介绍了。

2.优先级调度

轮转调度默认所有进程一样重要。而拥有和操作多用户计算机系统的人对不同的进程有不同级别。就好像等级顺序一样。

又或者你在看电影,而你后台的一些收发邮件的守护进程显然比你电影的进程优先级低。

为了防止高优先级无限运行,可以设置时间中断,每过一段时间降低优先级等级。

优先级极可能会造成饥饿现象。

3.多级队列 

 

 比如最高优先级属于一个队列运行一个时间片,次高运行2个,依次往下。当一个进程用完分配的时间片后,它被移到下一类。

4.最短进程优先

老化算法改进运行时间(aT0+(1-a)T1),a的值是尽快忘掉老时间的系数。找出最短时间的进程。其他与SJF基本相通

5.保证调度

向用户做出明确的性能保证,然后实现。假设n个进程并等价,那么每个进程将获得CPU处理能力的1/n。由于已经可以得出每个进程的实际运行时间。然后将它与实际运行的时间比较。按照其比率转向比率较低的进程,知道比率超过它的最接近的竞争者。

6.彩票调度

向进程提供各种系统资源的彩票。一旦需要做出一项调度决策时,就随机抽出一张彩票,拥有该彩票的进程获得该资源。按照彩票的配额分给CPU的份额。

7.公平分享调度

从用户角度考虑,换句话来说从进程的所有者来考虑。取决于公平的定义......

-------下一篇写关于线程的把...太多辣。