zoukankan      html  css  js  c++  java
  • 【知识强化】第二章 进程管理 2.2 处理机调度

    在这个小节中我们会学习处理机调度的基本概念

    和几个调度的层次,分别为高级调度、中级调度和低级调度。其中由中级调度,也就是内存调度我们会引出一个、补充一个课本上没有太多提及的知识点,就是进程的挂起态,并且会介绍一个进程状态的七状态模型,之后我们还会介绍三个调度层次的联系和对比。

    那么什么是调度?其实调度这个概念和我们的生活离的并不遥远。比如说在我们去银行的时候,这个银行它可能只有几个窗口可以为客户服务,那么这些客户,到底应该先为谁服务呢?银行一般采用的就是先到先服务的这种原则,那如果说此时有一个VIP客户,这个客户在这个银行里存了几个小目标,就是存了几个亿,那么这个VIP客户可能就会被银行优先地服务,它的优先级更高。再看另外一个场景,早上咱们起床的时候,可能每个宿舍只有一个卫生间,但是大家都想成为这个坐在王座上的男人。那么每个人都想使用,但是有的人说我想要使用三分钟,有的人要十分钟,有的人要一分钟,还有一个人他也需要使用三分钟。那大家经过商量之后就决定了一种使用这个资源的一个原则,就是时间使用的短的可以让它先使用,而时间长的就后使用。如果说时间长度相同的那么就先进入这个队列,先排队的就可以先使用,所以大家经过商量之后就决定用③①④这样的顺序来使用卫生间这个资源,所以其实所谓的调度它就是指,当我们有一堆东西、一堆任务要处理的时候,由于当前的资源有限,那么这些事情没办法同时地被处理。那这个时候我们就需要按照某种规则,比如说先到先服务或者说时间短的优先这样的规则来决定我们要用什么样的顺序来处理这些任务,这就是所谓的调度研究的问题。那么再来看什么是处理机调度,在多道程序系统当中,一般来说进程的数量是要比处理机的个数更多的,所以这就发生了刚才咱们所说的资源数量并不能满足同时为这么多的进程同时服务这样的事情,所以我们就需要决定一种顺序来为这些进程依次地服务,那么这就是所谓的处理机调度研究的一个问题,就是指我们要从就绪队列当中按照一定的算法来选择一个进程然后把这个处理机分配给它。

    那么我们先来看一下高级调度的问题。在早期的多道批处理操作系统当中,用户会首先通过外围机或者外围的一些输入设备把自己的作业输入到一个更高速的磁盘或者硬盘这样的外存空间上。但是由于内存的地址空间是有限的,我们并不能直接把所有的这些作业全部一口气放到内存当中,装不下,所以这就出现了刚才我们所说资源不够的问题,因此这种情况下我们就需要用调度来解决,来决定到底先把哪一个作业先调入内存,让它运行,所以这就是所谓的高级调度或者说作业调度管的东西。会按照一定的原则从外存的后备队列、后备作业队列当中选择一个作业,然后把它调入内存,并且会给它分配相应的一些系统资源,建立进程的PCB。只有建立了进程之后,它才可以获得竞争处理机的权限。就像这个样子,会建立它的PCB。那么高级调度可以看到,它其实是外存和内存之间的一个调度,并且每一个作业它只可能被调入一次,刚开始被调入,然后当作业运行结束之后再被调出。而作业被调出之前,它的作业的这个运行结果有可能是通过一种I/O设备把它输出,或者说输出到一个磁带或者硬盘上面,然后这些输出工作完成之后,系统会回收这个作业所占有的这些内存空间等等一系列的系统资源,

    并且会撤销它的PCB。那么可以看到,其实作业调出的时机肯定是这个作业运行结束了才把作业调出,而作业调入的时机才是需要操作系统来管理、来决定的一个问题,所以所谓的高级调度主要指的其实是调入的问题,因为只有调入的时候我们才需要选择,而调出的时候只要这个作业运行结束了,就立即把它调出就可以了。那么这就是高级调度。

    接下来我们再来看一下什么是中级调度。我们知道当一个作业被调入内存之后,它会建立起相应的一些进程。但是在第三个章节当中,大家会学到一个所谓的虚拟存储技术。这个地方大家只需要有个印象就可以,之后会有详细的学习。我们会把这个内存当中暂时有可能运行不到的这些进程把它相关的一些数据调到外存等待,然后一直到这个进程重新具备了运行的条件或者说内存又有空闲空间的时候再把这个进程相应的数据给调回内存。这么做的目的很显然就是可以提高内存空间的利用率,我们可以尽可能地保证当前处于内存当中的这些进程都是可以运行的这些进程。这样的话系统资源的利用率就会更高,并且系统的吞吐量也会相应的增大。

    就是这个样子。

    但是这些进程被调到外存之后,之后它还需要被重新地调回内存,继续执行下去。那这个过程就也需要我们用调度来选择,我们到底是先把哪一个进程相关的数据把它调回内存让它执行呢?这就是中级调度管的东西。那么当一个进程它相关的数据被调到外存之后,这个进程的状态会变为一种所谓叫做挂起状态。这是咱们之前没有提到过的一种进程状态,在王道书里也没有具体地聊过,但是考试当中挂起状态相关的内容也是有可能在选择题当中被考察的。这些进程被调出外存之后它们的PCB其实是会常驻内存的,并不会跟着一起调出外存。因为操作系统还需要继续对这些进程进行管理,而这些进程相关的管理的数据都存在PCB当中,所以PCB当然是需要常驻内存的。

    那么操作系统会为这些处于挂起态的进程建立一个所谓的挂起队列,把这些进程的PCB给用一个队列的方式把它组织起来,这个挂起队列就有点类似于咱们之前提到的所有的处于就绪态的进程把它组织成一个就绪队列,然后阻塞态的进程把它组织成一个阻塞队列,这其实都是为了操作系统方便管理而设计的一种机制。那么当这些进程需要被重新调入内存运行的时候,就会使用到所谓的中级调度或者叫内存调度。这个时候就需要决定我们需要把挂起队列当中的这些进程哪一个的数据先把它调回内存。相比于之前提到的高级调度,每一个作业只会被调入一次,调出一次这样的情况来说中级调度其实是可能会发生多次的。一个进程它有可能被多次的调出,多次的调入,所以中级调度的发生频率显然要比高级调度要更高一些。

    那么既然提到了挂起状态,我们再来补充一个和挂起状态相关的七状态模型。其实挂起状态又可以进一步地细分为就绪挂起和阻塞挂起两种状态。咱们之前已经学了进程的五状态模型,这也是408里要求掌握的一个进程的状态模型。但是对于一些自主命题的学校来说,也有可能会考察七状态模型,所以大家也不要掉以轻心。那么在引入了就绪挂起和阻塞挂起两种状态之后,一个处于就绪态的进程如果说此时这个系统的负载比较高,那内存空间已经不够用了。那么它有可能会把一个处于就绪态的进程,把它暂时调到外存当中,然后这个进程就进入了一个就绪挂起的状态,一直到内存空间空闲又或者说这个进程又需要继续执行。那么这个进程又会被激活,把它的数据相应的数据又挪回内存当中。这样的话一个就绪挂起的进程,又回到了就绪态。除此之外,一个处于阻塞态的进程,也可以被挂起。相应的,也可以再重新地被调入内存,然后进行激活,重新回到阻塞态。而有的操作系统也有可能会使一个处于阻塞挂起的进程,当它等待的阻塞事件发生的时候,这个进程就会直接进入到一个就绪挂起的状态。然后之后当它再被重新被调回内存的时候是直接回到就绪态而不是回到阻塞态。而有的时候一个进程当它处于运行态,运行结束之后,可能这个进程下处理机的时候就会被直接放到外存当中,让它进入就绪挂起的状态。而有的时候一个处于创建态的进程,当它创建结束之后,创建完PCB之后也有可能出现内存空间不够的情况,那这种情况下也有可能处于创建态的进程之后会先进入到一个就绪挂起的一个状态。那么这就是所谓的七状态模型。那大家需要注意的是挂起和阻塞的区别,这两种状态是都是暂时不能获得CPU服务的两种状态,但是区别在于处于挂起态的进程的进程映像是放在外存里的,而处于阻塞态的进程它的进程映像其实还在内存当中。而有的操作系统也有可能会把这些处于就绪挂起和阻塞挂起的这些进程分为两个不同的挂起队列,当然也有的操作系统还会根据这个阻塞的原因不同再把阻塞挂起的这些进程再细分为多个队列。那么这就是七状态模型,大家也需要注意一下。

    最后我们再来介绍调度的第三个层次——低级调度。所谓低级调度也可以称之为进程调度,那么进程调度主要的任务就是按照某一种算法从就绪队列当中选择一个进程为它分配处理机资源,把它调到处理机上运行,这就是所谓的进程调度。进程调度它很显然它是实现这个进程并发运行的一个基础,所以进程调度它也是操作系统当中最基本的一种调度,是最基本的一种调度。所以在一般的操作系统当中都会配置进程调度相关的一些模块、策略。那么为了实现进程的并发执行,进程调度的频率就有可能会很高,一般来说几十毫秒就会进行一次进程调度,只有这样才可以让这些进程在宏观上看是可以并行地执行的,而微观上其实它们是用很快的频率交替地执行的。这就是第三种——低级调度。

    我们再来整理一下三层调度的联系和对比。这三层调度分别要做什么相信刚才的讲解应该已经比较细了,这儿就不再展开。那么高级调度和中级调度这两层调度是发生在外存和内存之间的调度,区别在于高级调度它是面向作业的调度,一个作业在刚开始会被调入一次被调出一次,并且作业调入的时候会为这个作业建立相应的PCB,也就是建立它相应的进程。而中级调度(内存调度)它是面向进程的一种调度,它是把暂时不会运行的进程相关的进程映像、相关的一些数据把它调到外存里,然后之后通过中级调度再把这些进程的数据从外存调回内存。而低级调度它是内存和CPU之间的一个调度。对于这三层调度的发生频率来说,它们的发生频率依次是从低到高的。而这三种调度对进程状态的影响是高级调度,它有可能会使一个进程从无到创建态,最后当它创建完了PCB创建完毕之后,还会把这个进程放入到就绪队列里,让它进入就绪态,所以它对进程状态的影响的是这个样子(无->创建态->就绪态)。而内存调度它会使一个处于挂起态的进程重新回到就绪态,而如果挂起态又细分为阻塞挂起和就绪挂起的话,那么也可以说它可以使一个处于阻塞挂起的进程从新回到阻塞态。而低级调度也就是进程调度,它是选择一个处于就绪态的进程让它进入运行态,投入处理机开始运行,所以这是这三种调度对进程状态的影响。

    那么我们再来简单回顾一下,这个小节我们介绍了处理机调度的基本概念和三个调度的层次。我们需要注意的是这三种调度的后面一种名称,这三个名称才是在咱们的考题当中最高频、最容易出现的一种名称,所以这个大家需要注意。另外我们需要理解三层调度的联系和对比,大家在脑子里再回忆一下、对比一下,那么我们还通过中级调度引出了一个咱们书里没有具体介绍的一个知识点,就是所谓的挂起态,并且介绍了和挂起态相关的七状态模型,这两个知识点其实在考试当中也是有可能被考到的,特别是自主命题的一些学校。那么最后我们需要注意的是,咱们在介绍这几种三层调度的时候,都是说它们都是按照某种规则。那么这个课当中我们主要学习的是作业调度和进程调度相关的这些所谓的规则,而这个就是咱们之后要研究的调度算法的问题。

    在这个小节中我们会继续学习进程调度相关的一系列知识点。

    首先我们会来回答一下进程调度的时机是什么,什么时候需要进行进程调度,而什么时候又不能进行进程调度。并且在聊这个进程调度时机的问题的时候,会引出一个进程调度的方式的问题,分为非抢占式和抢占式两种。另外进程调度的目的其实是为了进程切换,那么进程切换和进程调度有什么区别呢?进程切换的过程当中我们又需要做一些什么事情呢?这些都是这个小节的内容。

    好的那么我们先来看一下进程调度的时机。之前我们已经介绍了进程调度的概念,进程调度,也叫做低级调度,就是指按照一定的算法,从就绪队列当中选择一个进程为它分配处理机。那么什么时候需要进行进程调度和切换呢?主要可以分为两个大类,第一种就是当前运行的这个进程它主动地放弃了处理机,第二种是当前运行的进程被动地、被迫地放弃了处理机。比如说如果一个进程它正常地终止,或者因为运行的过程当中发生了某种异常而不得不终止,再或者一个进程它发出了一个I/O请求,然后主动地请求进入阻塞状态,然后用来等待I/O完成。这些情况都是进程主动放弃处理机的一个具体的例子。那么被动放弃处理机就比如说,给这个进程分配的时间片用完了,或者说有一个更紧急的事情需要处理,再或者当前有一个优先级更高的进程进入了就绪队列。那么这些情况下又有可能需要把这个当前运行的进程强行地剥夺它的处理机使用权,然后它就不得不被动地放弃处理机。而进程调度并不是什么时候都可以进行的,有的时候不能进行进程调度和切换。比如说在我们处理中断的过程当中,由于中断处理它的过程是很复杂并且和硬件是息息相关的,因此在中断处理的过程中,是很难做到就是中断处理处理到一半,去进行进程调度和切换的。而第二情况是进程在操作系统内核程序临界区中,这种情况也不能进行进程调度。这点不太容易理解,之后咱们还会继续展开细聊。第三种情况是在原子操作的过程中,也就是之前咱们介绍过的一些原语,比如说咱们之前讲原语的时候举过一个例子。在一个进程它的状态发生改变,比如说从阻塞态变为就绪态的时候,那么我们既需要修改进程PCB当中这个进程状态的标志位,同时也需要把PCB放到一个新的相应的就绪队列里。那么如果说我们只做了前面这一件事,中间就开始进行进程切换、进程调度了,那么就有可能导致PCB当中记录的这种状态标志和PCB实际放的这个就绪队列还是阻塞队列实际放的这个位置不相匹配的这种情况,而这种数据的不匹配就有可能会为系统造成一些安全隐患,所以说这种原语或者说原子操作中间的过程肯定是不能允许进行进程切换的。

    那么接下来我们再来细聊一下第二个问题,进程在操作系统内核程序临界区中不能进行调度与切换,这是正确的一种表述。但是大家在做一个课后习题的时候会发现12年的一个题当中,有一个选项是说进程在处于临界区时不能进行处理机调度,这个表述是错误的。在了解内核程序临界区和普通的临界区的区别之前,我们需要先聊一个现在暂时还没有接触的概念,叫做临界资源。临界资源就是指一个时间段内只允许一个进程使用的资源,各个进程需要互斥地来访问临界资源。你访问的时候我不能访问,我访问的时候你不能访问,这是互斥的意思。那么临界区就是指访问临界资源的那段代码,因此各个进程肯定也只能互斥地进入临界区,互斥地执行这段访问临界资源的代码。而内核程序的临界区,也就是前者,一般就是用来访问某一种内核数据结构的,比如说进程的就绪队列。那么当一个进程此时它处于一个内核程序临界区,并且这个临界区它是要访问就绪队列的话,那么在访问之前它会把这个就绪队列上锁。而如果说这个进程当前还没有退出内核程序临界区的话,也就意味着这个临界资源并没有被解锁。那么在没有解锁的过程中,如果说我们要发生进程调度的话,那么进程调度相关的程序肯定是需要访问就绪队列这个临界资源的。因为它要从就绪队列当中挑选一个进程,为它分配处理机。那么由于这个就绪队列这个临界资源它此时还是上锁的一个状态,所以如果说在这种情况下去进行进程调度的话,那么这个进程调度肯定是没办法顺利地进行下去的。因为此时这个就绪队列还没有解锁。

    所以可以看到,对于内核程序临界区访问的这些临界资源,也就是这些内核结构而言,如果这些内核数据结构,这些临界资源,被上锁了并且没有被尽快地释放的话,那么有可能会影响到操作系统内核其他的管理工作。就比如说咱们刚才聊到的进程切换,所以说我们在访问这些内核程序临界区的这些期间内,我们不能进行进程的调度和切换。我们必须让这个进程迅速地尽快地执行完内核程序临界区的那些代码,然后完成对这个临界资源的访问。之后就尽快地把这个对临界资源的锁给解除,只有这样其他的操作系统内核才可以继续有序地进行管理工作。而另外一种情况,假如此时这个进程访问的是一种普通的临界资源,比如说是一个打印机的话,那么它在访问它的时候会先进行上锁,那打印机在打印完成之前,这个进程其实是一直在临界区内的。它还一直保持着对打印机的访问,但是由于它还没有退出临界区,所以这个临界资源并不会被解锁。但是打印机它又是一种慢速的I/O设备,如果这个情况下不允许进程调度、进程切换的话,那么就会导致这个进程它需要一直空等着这个打印机的打印结束,所以在这个进程空等的过程当中,它同时还霸占着CPU,所以CPU可以一直说是空闲的状态,它一直没有做一些有意义的事情,所以如果说这个进程在访问一个普通的临界资源,在一种普通的临界区当中的话,这个情况下其实是应该进行进程调度的。

    因为普通的临界区访问的这些普通的临界资源,并不会像之前所说的这个例子一样,直接地影响到操作系统内核的管理工作。所以说为了增加系统的并发度,增加CPU的利用率,那么在访问这些普通的临界区的时候,是可以进行进程调度和切换的。那么讲到这里,刚开始的这两个问题,为什么前者对为什么后者错,相信大家已经有所理解了。

    那么接下来我们再来看下一个问题。在有的操作系统当中,它只允许进程主动地放弃处理机,而不允许这个进程在运行的过程中,被迫地被剥夺处理机资源。但是又有的操作系统,它是允许当有更紧急的任务需要处理的时候,它是会强行地剥夺这个当前运行进程的处理机资源的,所以由这个问题就是当前运行的进程是否可以被强行地剥夺处理机资源这个问题,我们引出了下一个知识点。

    就是进程调度的方式,分为非剥夺调度方式和剥夺调度方式。前者又可以称作非抢占式,后者又可以称作抢占式。那么非剥夺调度方式就是咱们刚才聊到的只允许进程主动地放弃处理机这样一种方式,除非这个进程它正常或者异常地终止,或者它主动地要求进入阻塞态,不然这个处理机是会一直为当前运行的这个进程所为它服务的。那么抢占式或者说剥夺调度方式的话,如果说此时有一个更重要更紧急的任务需要处理的话,那么这个当前执行的进程就会被暂停执行,被剥夺处理机资源,然后把处理机分配给更重要、更紧急的那个进程进行处理。那显然前面这种方式它的这个规则会相对来说要简单一些,所以这种方式实现起来要简单,并且系统管理的开销也要更小。但是缺点就在于它没有办法及时地处理紧急任务,所以这种非抢占式只适合于早期的一些批处理系统。而后者,抢占式,它可以优先地处理更紧急的进程,并且可以让各个进程按照时间片轮转的这种方式来执行。当时间片到的时候,就可以强行地把当前运行的进程把它的处理机资源给剥夺,所以说后面这一种方式,它就比较适合于后面出现的分时操作系统和实时操作系统。这就是进程调度的方式的问题,分为这样两种。

    那么既然我们选择了一个进程要为它分配处理机的话,在进程与进程切换的过程当中,又发生了一些什么事情呢?首先我们来聊一聊狭义的进程调度和进程切换有什么区别?狭义的进程调度指的是从就绪队列中选中一个要运行的进程这样一个过程。而这个要运行的进程它可以是刚刚才暂停执行的进程,也可以是另一个进程。如果选中的是另一个进程的话,那么我们就需要进行进程切换。而进程切换指的就是之前的那个进程让出处理机,然后之后的进程占用处理机这样的一个过程。而有的题目当中出现的进程调度,它指的是广义的进程调度,广义的进程调度包含了进程切换和选择一个进程这样前面的就是前面所说的这两个步骤,所以在读题的时候如果出现了两种调度的含义大家不要觉得奇怪,自己能够分辨它是狭义的还是广义的就可以了。那么进程切换的过程主要完成了什么事情呢?其实我们可以把这个过程简化为两件事情,第一件事就是把对原来正在运行的那个进程它的各种数据包括处理机的运行环境这些数据把它保存下来。第二件事就是把新的进程的各种各样的运行环境之类的数据把它恢复过来。而运行环境、运行现场的一些信息,比如说程序计数器、程序状态字然后各种数据寄存器,这些信息一般是存在进程控制块PCB当中的,所以对这个数据进行保存其实是保存到了PCB当中。而对这些数据进行恢复,其实是从PCB当中读出这些数据,并且把这些数据放到相应的寄存器当中。那么经过刚才的分析我们会发现,进程的切换其实并不是一瞬间就可以完成的,它是需要付出一定的时间代价的,所以我们不能简单地认为进程切换越频繁,进程的并发度就越高。如果进程的切换、调度过于频繁的话,其实反而会导致整个系统的效率降低。因为系统会把大部分的时间都花在这个进程切换的这个开销上,而真正用于执行进程、推进进程的时间反而会减少,所以进程切换是有代价的。了解这一点对于理解咱们之后讲时间片的一个调度算法是至关重要的,这个地方大家稍微注意一下。

    好的那么我们再来快速回顾一下这个小节的内容。这个小节的内容并不多,并且也不算是考试的重点,不过大家也需要理解。首先我们介绍了进程调度的时机,包括什么时候需要进程调度,分为进程主动放弃处理机和进程被动放弃处理机这两种情况,并且我们举了一系列的例子。之后我们介绍了什么时候不能进行进程调度。重点介绍了进程在操作系统内核程序临界区当中为什么不能进行进程调度,因为这个时候进程进行进程调度有可能会影响到操作系统内核的一系列管理工作。而如果进程处于一个普通的程序临界区当中,它访问的是一个普通的临界资源的话,这种情况下是可以进行进程调度的。这点是不太容易理解的难点,但是也不算重点。那么之后我们又介绍了进程切换的过程,其中大家最需要注意、最需要理解的是,进程的调度和切换是有代价的。只需要知道这一点就可以了,其他的这些有一个大体的印象就可以。另外呢我们还介绍了进程调度的两种方式,分为抢占式和非抢占式,而这两种调度方式会在之后咱们讲调度算法的时候大量的出现,所以继续学习后面的内容会对这两个部分的理解会更加深入。

    在这个小节中我们会学习一系列用于评价一个调度算法好坏的一些评价指标,包括CPU利用率、系统吞吐量、周转时间、等待时间和响应时间。那在学习的过程中大家要注意理解各个指标为什么这么设计,并且要会计算每一个指标。

    首先来看一下什么是CPU利用率,其实在早期的计算机当中,计算机的造价是很昂贵的,特别是CPU这个部件的造价占了很大一部分。它的这个东西基本就是用钱堆出来的一个很奢侈的东西,并且在现代的这些计算机当中其实CPU也不便宜,所以因为CPU这么贵,那么人们就会希望让CPU尽可能多地为人们工作,所以就设计了一个叫做CPU利用率的这样一个指标。这个指标就是用来表示CPU处于忙碌的时间占总时间的比例。那么这个利用率,就可以用忙碌的时间比上总时间就可以算出这个利用率。但是有的题目它不仅仅是会让我们算CPU利用率,还会让我们算某种比如说某种I/O设备的利用率。比如说如果一个计算机当中,它只支持单道程序,然后有一个作业刚开始的时候需要在CPU运行5秒,然后打印输出5秒之后再执行5秒然后就结束。那么在这个过程中CPU利用率就是先刚开始运行了5秒,然后之后又运行了5秒,总共运行了10秒。CPU处于忙碌的时间是10秒,然后整个过程处理的时间是5+5+5也就是15秒,那么就是66.66%将近是这样子。然后打印机的利用率的话就是打印机处于忙碌的时间也就是5秒,再比上总时间那么就是33.33%,大概是这样。但是在真正的考研题目当中通常会考察多道程序并发执行的情况,这种情况下大家可以用甘特图来辅助计算。这个地方先不展开,在课后习题会有遇到,并且也会有相应的讲解。

    那么第二个评价的指标就是叫做系统吞吐量,那么对于计算机来说,计算机它肯定是希望用尽可能少的时间可以处理完尽可能多的作业,所以就设计了一个叫做系统吞吐量的指标,用来表示单位时间内完成了多少道作业,所以系统吞吐量可以用总共完成了多少道作业再除以总共花了多少时间就可以算得系统吞吐量。比如说有个计算机处理完十道作业花了100秒,那么吞吐量就是10/100那么就是0.1道每秒,也就是平均每秒可以完成0.1道作业,这就是单位时间内完成的作业的数量。那这就是系统吞吐量。

    第三个指标是周转时间。对于计算机的用户来说,这个用户肯定是很关心自己的作业从提交到完成总共花了多少时间。一般来说这个时间当然是花的越少越好,所以周转时间就是用来反映这样一个所花费时间的一个指标。就是指从作业被提交给系统开始,到作业完成为止这段时间到底有多长。那么它总共这个周转时间,总共包括四个部分,就是作业在外存的后备队列上等待被作业调度的时间,然后进程在就绪队列上的时间,还有进程处于运行态的时间,还有进程处于阻塞态的时间。后面的这三项就是就绪态、运行态和阻塞态,这三项在整个作业的处理过程当中是会发生多次的。整个过程中只会有一次作业调度,这个咱们在之前的小节当中也有介绍过,所以一个作业的周转时间我们可以用作业的完成时间减掉作业被提交给系统的时间,这样就可以简单地计算出来。另外呢对于操作系统来说,它肯定是会更关心系统的整体表现,所以它会更关心所有的作业周转时间的一个平均值,所以就有另外一个指标叫做平均周转时间。就是用各个作业的周转时间之和,再除以作业的数量。那么我们再来思考一个这样的问题,对于各个用户提交的这些作业来说,有的作业它的运行时间是短的,有的作业的运行时间是长的,所以说如果在周转时间相同的情况下,其实运行时间更长的那些作业对于用户来说肯定感受会稍微更好一些。举一个很直观的有违道德的例子,比如说我们去排队等厕所,那么你本来只需要使用一分钟,但是你要排队排十分钟,这总共整个周转过程你总共花了十一分钟。这种感受肯定是很糟糕的了,本来自己只需要用一会,但是又需要等待那么长的时间。不过对于另外一个人来说,它总共需要使用十分钟,但是它只需要等一分钟,所以另外这个人他的整个周转时间其实也是十一分钟。只不过这十一分钟当中只有一分钟是用来等待的,所以对于第二个人来说这一分钟的等待其实对他来说感受没有那么糟糕,所以这就是在周转时间相同的情况下作业的这个实际运行时间长短不同所导致的对于用户的感受的这种区别,因此人们又提出了另外一个指标叫做带权周转时间,就是指作业的周转时间再比上作业实际运行的时间,因此可以看到对于周转时间相同的两个作业来说,它的如果哪个作业的实际运行时间更长,那么这个作业相应的被服务的这个时间所占的比例也就更多。那么这个带权的周转时间就会更小,用户满意度相应的也会更高。而对于实际运行时间相同的两个作业来说,肯定是周转时间短的那个作业对于用户来说他的满意度会更高。那么周转时间短的话相应的带权周转时间也会更小。所以通过这个式子我们会发现带权周转时间它肯定是大于等于1的,因为周转时间包含了作业的实际运行时间,它肯定比实际运行时间要更大。那么带权周转时间和周转时间都是一样的,它们肯定都是越小对于用户的体验来说就会越好。相应的,和平均周转时间一样,也会有一个所谓的平均带权周转时间。这个就是系统会比较关心的一个指标。这个就是把各个作业的带权周转时间给加和起来最后再除以一个作业数。那么这就是周转时间相关的四个指标。

    接下来我们再来看下一个指标叫等待时间。对于计算机的用户来说肯定是希望自己作业尽可能少地等待处理机。那么等待时间就是用来度量这个用户的作业等待处理机等待被服务的这个时间之和到底是多少。等待越长肯定用户的满意度就越低,那么我们先来看一下当一个作业刚开始被提交的时候,它是被放到了外存中的作业后备队列当中。作业在后备队列当中需要等待被服务也就是被作业调度。

    当它被调度以后,

    这个作业就会放到内存当中,并且建立起相应的进程。当这个进程建立了之后,它会被CPU服务也会被I/O设备服务,当然也会有等待被服务的这样一些时间,一直到最后整个进程结束,然后把作业移出内存。那么对于进程来说,一个进程的等待时间其实指的就是这个进程被建立起之后开始累计,它等待被服务的时间总和是多少。但是需要注意的是,它在等待I/O完成的这个期间,其实是正在被I/O设备服务的,所以这种时间是不能算到等待时间里的。另外呢,对于作业来说,我们不仅要考虑它建立了相应的进程之后的这一系列的等待时间,我们还要加上它在外存的后备队列当中等待被调度的这一段时间,所以作业的等待时间和进程的等待时间计算起来是有一些不同的,这个稍微注意一下。通过之后的课后习题大家会发现一个现象,就是一般来说一个作业它总共需要被CPU服务多久,被I/O设备服务多久,这个总时间一般来说都是确定不变的,所以调度算法其实只会影响作业或者说进程的一个等待时间。当然和之前的那些指标一样,等待时间也有一个与它对应的指标叫做平均等待时间。那么平均等待时间就是把所有进程或者作业的等待时间做一个加和再除以作业的数量就可以了。

    最后我们再来讲一个叫做响应时间的一个指标,对于计算机用户来说如果说他提交了一个请求比如说就是在键盘里输入了一个调试命令,那么他肯定是希望尽早地被系统服务,被回应他提出的这个请求,所以响应时间指的就是这个用户从提出请求到首次产生响应所用的时间就叫响应时间。

    好的那么我们再来回顾一下,这个小节我们介绍了五种用来评价调度算法的指标。那么大家要理解各个指标为什么这么设计,并且还要会计算各个指标。其中CPU利用率和系统吞吐量咱们举了两个比较简单的例子,后面的其他的这些指标我们会在之后的对于算法的讲解当中再不断地进行实践,所以这个地方暂时没给出具体的例子。那这个小节当中比较容易忘记的是带权周转时间和平均带权周转时间这两个指标。那么大家需要结合咱们举的那个比较有味道的例子来理解这个指标为什么这么设计。只要理解了其实记住它就不难了。

    这个后备队列是在外存中的。如果说是用于进程调度的话,那么考虑的是哪一个进程先到达的就绪队列,就绪队列是在内存中的,这是当它作为作业调度或者进程调度的时候有的一个小小的区别。先来先服务的算法一般是非抢占式的算法,也就是说对于对于当前正在占用处理机的那个进程或者说作业。那么只有这个进程或者作业它主动地放弃处理机的时候,才会进行调度,才会用这个调度算法的规则来选择下一个应该得到服务的进程。

    各进程的等待时间、平均等待时间、周转时间、平均周转时间、平均带权周转时间是评价一个调度算法的指标。这些进程其实都是纯计算型的进程,也就是说这些进程其实只需要CPU为它们服务,所以说一个进程在它到达以后,肯定只会有两个状态,要么它就是在等待被CPU调度,要么它就是处于运行的状态,所以对于这个题目这种纯计算型的进程来说,我们只需要用它的整个周转时间来减掉它的运行时间那么剩下的肯定就是等待时间这个部分。但是有的题目可能会给出的是一些既有计算还有I/O操作的这些进程。那么在计算这些进程的等待时间的时候我们就不能简单地用周转时间减去运行时间这样来计算,我们需要用周转时间也就是它整个完成时间到到达时间这个总的时间段的长度减掉它在CPU上运行的时间,还要再减掉I/O设备为它服务的这个时间,这样得到的才是这种又有计算又有I/O操作的进程的等待时间。

     也就是说,对于一个排在长作业后面的短作业或者排在长进程后面的短进程来说,它需要等待很长的时间才可以被服务。那么对于短进程或者短作业的用户来说,就体验会特别糟糕,所以先来先服务算法其实是对长作业有利,对短作业不利的。对于先来先服务算法来说,其实是不会导致饥饿的。因为不管是哪个作业,它只要一直等着,反正它前面的那些作业或者进程总会被处理完,所以它是不会导致饥饿的,这就是先来先服务算法。先来先服务算法对于带权周转时间,还有平均等待时间,这些指标其实是不太优秀的,所以短作业优先算法的提出其实就是为了追求更少的平均等待时间还有平均周转时间、平均带权周转时间。

    那短作业优先算法它的规则也很简单。

    根据要求时间也就是运行时间来做优先级的排列。和之前先来先服务算法得到的这三个指标平均等待时间、平均周转时间、平均带权周转时间来进行一个对比会发现,使用了非抢占式的短作业优先算法之后,平均周转时间从8.75降为了8,平均带权周转从3.5降为了2.56,而平均等待时间从4.75降为了4,所以从这三个指标来看,短作业优先算法在这些方面的表现它是要优于先来先服务算法的。

    当前这个正在运行的进程如果被抢占处理机之后它就会回到就绪队列当中。另外呢,如果说当前运行的进程主动放弃处理机的时候,也就是一个进程它正常地完成的时候,也需要用这样的调度算法来进行一个调度,所以这是这种算法当中我们需要注意的两个时间点。一个是就绪队列改变的时候,另外一个是一个进程完成的时候。那么我们按照这样的规则来依次分析一下各个时刻。进程P2到达,就会发生短作业

    抢占式的短作业优先算法中,这些进程的执行可能是断断续续的。这和咱们之前介绍的那两种算法——非抢占式的短作业优先算法和先来先服务算法是不太一样的。采用了抢占式的短作业优先或者最短剩余时间优先算法之后,得到的平均周转、平均带权周转还有平均等待时间这三个指标比非抢占式的还要更小。也就是说,采用了抢占式的短作业优先算法(最短剩余时间优先算法)之后,它在这些方面的表现要优于非抢占式的短作业优先算法。

    除了要了解抢占式的短作业优先算法(最短剩余时间优先算法)和非抢占式的短作业优先算法在具体的做题过程当中有什么区别之外,我们还需要注意几个小细节。如果未特别说明,短作业优先调度算法默认是指非抢占式的短作业优先调度算法。其实最短剩余时间优先算法所得到的平均等待时间和平均周转时间还要更少。在所有的进程同时可运行的时候,采用短作业优先调度算法(非抢占式的短作业优先调度算法)所得到的平均时间或者平均周转时间是最少的。或者我们还可以改一种说法,如果说所有的进程几乎都是同时到达的,那么采用这种短作业优先调度算法得到的平均等待时间和平均周转时间是最少的。为什么要用一个几乎?因为进程的到达肯定还是有先后顺序的。只不过在宏观上看我们可以认为就是连续到达的那些、很快速的到达的那些进程几乎是同时到达的。然而它们事实上也会有先后顺序,只不过是微观上看有先后顺序,宏观上看这些进程几乎同时到达。还有另外一种说法,如果说我们不要这个“所有的进程几乎都同时到达”这个条件的话,我们可以说抢占式的、就是刚才所提到的那个最短剩余时间优先这个算法所得到的平均等待时间和平均周转时间是最少的,这个是没有问题的。数学基础好的同学可以证明一下为什么这个最短剩余时间优先算法的平均等待时间、平均周转时间最少。虽然短作业优先算法它的平均等待时间、平均周转时间不一定是最少的,但是相比于像先来先服务还有最高响应比优先,相比于这样的算法来说,短作业优先算法仍然可以获得比较少的平均等待时间、平均周转时间这两个指标的。计算机学科和数学、物理这些基础理学的学科不太一样,它并没有一个很严格的说法。在考试的时候,最好就是判断一下所有的选项然后选一个错误更少的、更合适的选项。

    短作业优先调度算法它的优点就是可以得到最短的平均等待时间和平均周转时间。这个“最短”是有双引号的,短作业优先调度算法可以得到最短的平均等待时间和平均周转时间是有一定条件的和一定适用范围的,你知道这句话不严谨这样一个细节就可以了。缺点其实也很明显,就是对于短作业有利,长作业不利。如果说这个就绪队列中源源不断的有更短的作业到来的话,那么就有可能会产生长作业饥饿的现象。作业/进程的运行时间其实是由用户提供的一个数据,所以用户可以把自己本来是长作业但是把自己提交的这个数据把它写的很短,所以事实上短作业优先这种算法并不一定真正的能够做到短作业优先这件事。是会导致饥饿的,更加严重的饥饿现象就可以称做进程饿死或者作业饿死,这就是短作业优先算法。

    先来先服务算法对长作业友好,对短作业不友好的问题。短作业优先算法会导致对长作业不友好,甚至会导致长作业饥饿的这种现象。

    高响应比优先算法既要考虑它的运行时间,还要考虑到要求服务的时间,也就是估计的运行时间。高响应比算法的规则相对来说要复杂一些,在每一次调度的时候选择一个响应比最高的进程为他们服务。那响应比的

    这些是纯计算型的进程,不会有I/O操作,也就是说不会主动地要求阻塞。

    对于一个长作业来说,随着等待时间越来越大,那么它的响应比肯定也会越来越大,所以它被调度的机会也会越来越高,所以这个算法也避免了短作业优先这个算法造成的这个长作业饥饿的问题,所以这个算法其实是不会导致饥饿的。

    短作业优先算法它得到了“最短的”平均等待和平均周转时间,先来先服务它要求绝对的公平,另外呢这三种算法还追求平均等待时间、平均周转时间这些,这些其实都是用来评价系统的整体性能和整体表现的指标。这三种算法的交互性很糟糕,主要用于早期的批处理系统当中。在早期的批处理阶段计算机也很昂贵,所以人们更追求系统的整体表现而不是对于各个用户来说的一种用户体验。先来先服务算法现在也经常结合其他算法一起使用,所以先来先服务算法在现代计算机当中也扮演着很重要的角色。

     

    时间片调度算法它一般是用于进程调度的,因为所谓时间片其实指的是处理机的时间片,而一个作业只有当它放入了内存并且建立了相应的进程之后,只有作为进程它才有可能被分配处理机的时间片。因为进程肯定是执行的基本单位,所以说这个算法一定是用于进程调度的。而通过刚才的这个描述我们会发现,当一个进程它的时间片用完之后,虽然说它还没有结束,但是有可能会被强行地剥夺处理机这个资源,所以说这种算法肯定是一种抢占式的算法,并不一定要等到这个进程主动地放弃处理机才会发生调度,而这种抢占、时间片的切换是由时钟装置也就是某一种计时的硬件来发出时钟中断来通知CPU时间片已到的。而时钟装置、时钟中断这些具体的内容会在计算机组成原理里面进行学习。如果不考计组的同学只需要有个了解、有个印象就可以了。

    时间片轮转调度算法它一般是用于分时操作系统的,比起之前所说的那些平均周转时间来说,这种类型的操作系统会更关心进程的响应时间,所以在这个地方我们也不再计算进程的等待时间、周转时间那些指标。

    如果每一个进程都可以在给自己分配的时间片之内就执行结束,所有的调度都只会发生在这些进程主动放弃处理机的时候,并且这些调度的顺序也会按照各个进程到达就绪队列的先后顺序来依次调度,那么这个算法就完全退化为了先来先服务的调度算法,所以如果时间片太大的话,当然也会增大这些进程的响应时间,就失去了时间片轮转调度算法最大的一个优点,所以时间片是不能选择的太大的。怎么理解它会增大各个进程的响应时间呢?

    如果我们把时间片设置的太小的话, 就会导致进程的切换过于频繁。进程的调度和切换由于需要保存、恢复运行环境,中间处理一些其他的事情,所以调度和切换其实是需要付出一定的时间代价的,所以如果说进程切换过于频繁,那么系统会花大量的、大部分的时间来处理进程切换,中间的这些事情,从而导致我们实际进行进程运行、进程执行的时间比例反而会减少,所以时间片选择的太小也是不利的。

    时间片轮转调度算法的优点很明显,就是对各个进程都是公平的,会轮流地为它们服务,并且响应很快,只要我们设置的时间片大小是合理的,那么就会在一定的时间间隔内就可以给各个进程、各个用户都有一个响应,所以这种调度算法就比较适合于分时操作系统,可以为各个用户分配一个大小的时间片。而缺点呢就是用于进程切换的时候会有一定的开销,另外这个算法它并不区分任务的紧急程度。这种算法是不可能导致饥饿的,因为它肯定是轮流地会为各个进程服务。时间片太大或者太小分别会有什么影响,这个在选择题当中经常会作为考查。那以上就是时间片轮转调度算法。

    优先级调度算法会为每一个作业或者进程设置一个优先级,然后在调度的时候会选择一个优先级最高的一个进程或者作业进行调度。那么这个算法的规则并不复杂。优先级调度算法用于作业调度的时候就是把一个处于外存后备队列当中的作业选择它然后进入内存,然后用于进程调度的时候是选择一个在内存的就绪队列当中的一个进程为它分配处理机。优先级调度算法甚至还可以用于I/O调度。非抢占式的我们只需要在一个进程主动放弃处理机的时候来检查,这个时候进行调度就可以。而如果说题目告诉我们,采用的是抢占式的优先级调度算法的话。那么当一个就绪队列发生改变的时候,我们也需要检查是否会发生抢占。

    优先数越大,优先级越高。优先数和优先级的概念并不一样,有的题目当中有可能是优先数越小,优先级越高,所以具体要看题目给出的信息和条件。既然采用的是非抢占式的优先级调度算法,我们只需要关注各个进程主动放弃处理机的时候的时刻就可以了。这就是非抢占式的优先级调度算法。

    如果采用的是抢占式的优先级调度算法,除了要关注各个进程主动放弃处理机这样的一个时刻之外,我们还需要关注这个就绪队列发生改变的时刻,我们要检查一下到底是不是会发生抢占,是不是当前到达的这个进程优先级要比此时正在运行的进程优先级还要更高。这就是抢占式的优先级调度算法的一个大体的过程。

    就绪队列其实未必只有一个,有的操作系统它是按照优先级来组织就绪队列的。如果说设置一个就绪队列的话,也有的操作系统是会按照优先级从高到低的顺序来动态地排队,就是调节这个就绪队列当中各个进程的位置。系统进程的优先级要高于用户进程,因为系统进程毕竟是作为管理者,所以管理者的优先级自然是要比被管理者要更高的。另外呢,前台进程的优先级要高于后台进程,这个其实在iphone、android这些手机上就是有这样一个原则。因为前台进程毕竟是现在用户能够看到的进程,所以这些进程的流畅程度啊之类的这些指标肯定是要比后台进程要更重要,所以它的优先级也理应要高于后台进程。操作系统会更偏好I/O型进程,I/O型进程又称作I/O繁忙型进程。与I/O型进程相对应的有一个计算型进程,也就是CPU繁忙型进程。那么为什么操作系统会更加偏好、更加优先地处理I/O繁忙型进程呢?I/O设备和CPU是可以并行地工作的,所以如果说我们让I/O繁忙型进程的优先级比计算型的进程更高的话,那么也就意味着I/O繁忙型的进程它可以优先地运行,而它越优先地运行,就越有可能让I/O设备尽早地投入工作,尽早地开始和CPU并行地工作,所以这就会直接地导致系统资源的利用率会上升,也就是I/O设备的利用率,这样的策略也会提升系统的吞吐量,所以操作系统更偏好I/O型进程,对整体的性能提升是有帮助的,在选择题当中也会出现、也会考查。之前讲过的高响应比优先算法,所谓的响应比,也是这样一个规则,就是当它等待的时间长了之后,响应比会增大。那么响应比其实就代表了这个进程的优先级,所以它的优先级也得到了提高,所以我们可以认为高响应比优先算法它就是一种动态的优先级的调度算法。如果一个进程频繁地进行I/O操作,那么就说明它很有可能是一种I/O繁忙型的进程。提高I/O繁忙型进程的优先级,这样系统资源的利用率也就是I/O设备的利用率还有系统的吞吐量这些指标也会得到提升。

    先来先服务算法它的最大的优点就是公平,而短作业优先这个算法的优点就是可以让短作业尽早地处理完,然后就可以追求到一个比较短的平均等待时间、平均周转时间。而时间片轮转调度算法它的优点就是可以让各个进程可以及时地得到响应。优先级调度算法又可以灵活调整各个进程被服务的机会,也就是通过优先级来进行控制。那么我们是否能设计出一种算法能够综合上面这些算法的优点,取一个折中平衡呢?

    多级反馈队列调度算法的规则比较复杂,一般是用于进程调度的。多级反馈队列调度算法的抢占规则也比较复杂,虽然说它是一种抢占式的算法,但是在实际的操作系统应用当中也有可能是把它实现为非抢占式的版本。但是考试的时候咱们就以汤子赢的教材为准,认为它是抢占式的算法,并且注意一下它在抢占的时候会发生什么事情。

    但是第一级队列的时间片大小只有一个单位的时间,所以当P1执行了一个单位的时间片之后,它的时间片就用完了。那么它在用完时间片之后还没

     

    多级反馈队列它有很多优点,就是对各种各样的进程都是相对公平的。每个进程刚开始进来的时候肯定都是会被优先处理的,因为刚开始的时候它的优先级是最高的,而这就是先来先服务的一个优点。每一个新到达的进程其实都可以很快得到响应,因为它的优先级高,在第一级队列的话,肯定很快就可以被调度,这就是时间片轮转调度的一个优点。另外短进程只需要经历过优先级比较高的那几个队列,就执行了几个较短的时间片之后就可以完成了,所以这也会导致就是这些短进程的平均周转时间会比较理想,而这就是最短进程优先这个算法的一个优点。另外呢短进程优先算法一般来说是要求用户来提供自己的进程大概需要运行多长时间这样的数据的,但是有可能会有用户作假,就是本来是长进程,它把自己的时间说的很短。多级反馈队列调度算法不必要事先估计这个进程的运行时间,从而避免了用户造假。当一个I/O型进程在运行的过程当中,因为发出I/O请求而主动地阻塞的时候,我们可以把这个进程当它再次被唤醒的时候,让它重新返回原来那一级的队列,而不是让它降到下一级队列。这种处理就会导致一个I/O密集型的进程,它可以长期地保持一个较高的优先级,保持在较高优先级的队列里。这个算法是有可能会导致饥饿的,因为如果说源源不断地有短进程到达的话,那么可能它短进程在第一级队列被分配一个较短的时间片之后就可以被处理完。这种进程源源不断地到来的话,那么已经降级为更低优先级的那些进程就有可能会长期得不到服务,从而也会导致饥饿的现象。

    我们需要注意的是优先级调度算法它是有抢占式也有非抢占式的版本。在做题的时候我们需要注意的是非抢占式的优先级调度算法,我们只需要注意各个进程主动地放弃处理机这样的时刻,我们在这个时刻检查是否需要调度就可以了。抢占式的优先级调度算法除了需要注意各个进程主动地放弃处理机这样的时刻,还需要注意就绪队列发生改变的时候是否会发生抢占这样的事情。这三种算法的优缺点是更不容易被考察的,是否会导致饥饿学会自己分析。这三种算法是比较适合用于交互式系统的,因为比起早期的这些批处理操作系统来说,这个计算机的造价其实是越来越低的,所以之后出现的这些交互式的系统,包括像分时操作系统还有实时操作系统,这些操作系统它会更注重对于各个进程的响应时间还有公平性、平衡性这些指标,而不是一味地追求批处理操作系统当中的平均周转时间这些很宏观的一些指标,所以这三种算法刚好比较适用于交互式系统的一系列需求,可以提供比较快的响应时间,也可以用一系列的策略来追求公平、平衡的这种性能,所以它们是适合用于交互式系统的。

  • 相关阅读:
    清除浮动的几种方法
    call() 、 apply() 、bind()方法的作用和区别!
    关于如何通过json更改背景图片
    js验证码实现
    解决python3 UnicodeDecodeError: 'gbk' codec can't decode byte
    Rest接口测试,巧用firebug插件
    PHP中字符串的连接和换行
    PHP内置函数file_put_content(),将数据写入文件,使用FILE_APPEND 参数进行内容追加
    PHP的三种输出方式
    PHP中的include、include_once、require、require_once
  • 原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/10703159.html
Copyright © 2011-2022 走看看