OS- -调度(一)

OS- -调度(一)

一、调度

  • 当一个计算机是多道程序设计系统时,会频繁的有很多进程或者线程来同时竞争CPU时间片
  • 当两个 或两个以上的进程/线程处于就绪状态时,就会发生这种情况。如果只有一个CPU可用,那么必须选择 接下来哪个进程/线程可以运行
  • 操作系统中有一个叫做调度程序(scheduler)的角色存在,它就是 做这件事儿的,该程序使用的算法叫做 调度算法(scheduling algorithm)
  • 尽管有一些不同,但许多适用于进程调度的处理方法同样也适用于线程调度
  • 当内核管理线程的时候, 调度通常会以线程级别发生,很少或者根本不会考虑线程属于哪个进程。

下面我们会首先专注于进程和 线程的调度问题,然后会明确的介绍线程调度以及它产生的问题。

1.调度介绍

  • 让我们回到早期以磁带上的卡片作为输入的批处理系统的时代,那时候的调度算法非常简单:依次运行 磁带上的每一个作业
  • 对于多道程序设计系统,会复杂一些,因为通常会有多个用户在等待服务
  • 一些 大型机仍然将 批处理和 分时服务结合使用,需要调度程序决定下一个运行的是一个批处理作业还是 终端上的用户。
  • 由于在这些机器中CPU是稀缺资源,所以好的调度程序可以在提高性能和用户的满意 度方面取得很大的成果。

进程行为

  • 几乎所有的进程(磁盘或网络)I/O请求和计算都是交替运行
    在这里插入图片描述
  • 如上图所示,CPU不停顿的运行一段时间,然后发出一个系统调用等待I/O读写文件。
  • 完成系统调用 后,CPU又开始计算,直到它需要读更多的数据或者写入更多的数据为止。当一个进程等待外部设备 完成工作而被阻塞时,才是I/O活动
  • 上面a是CPU密集型进程;b是I/O密集型进程进程,a因为在计算的时间上花费时间更长,因此称 为计算密集型(compute-bound)或者CPU密集型(CPU-bound) , b因为I/O发生频率比较快因此称 为I/O密集型(I/O-bound)
  • 计算密集型进程有较长的CPU集中使用和较小频度的I/O等待。I/O 密集型进程有较短的CPU使用时间和较频繁的I/O等待
  • 注意到上面两种进程的区分关键在于CPU 的时间占用而不是I/O的时间占用
  • I/O密集型的原因是因为它们没有在I/O之间花费更多的计算、而 不是I/O请求时间特别长
  • 无论数据到达后需要花费多少时间,它们都需要花费相同的时间来发出读取 磁盘块的硬件请求。
  • 值得注意的是,随着CPU的速度越来越快,更多的进程倾向于I/O密集型。这种情况出现的原因是 CPU速度的提升要远远高于硬盘。这种情况导致的结果是,未来对I/O密集型进程的调度处理似乎更 为重要。
  • 这里的基本思想是,如果需要运行I/O密集型进程,那么就应该让它尽快得到机会,以便发出 磁盘请求并保持磁盘始终忙碌。

何时调度

第一个和调度有关的问题是何时进行调度决策。存在着需要调度处理的各种情形。

  • 首先,在创建一个新 进程后,需要决定是运行父进程还是子进程。因为二者的进程都处于就绪态下,这是正常的调度决策,可以任意选择,也就是说,调度程序可以任意的选择子进程或父进程开始运行。
  • 第二,在进程退出时需要作出调度决定。因为此进程不再运行(因为它将不再存在),因此必须从就绪进程中选择其他进程运行。如果没有进程处于就绪态,系统提供的空闲进程通常会运行
什么是空闲进程
  • 空闲进程(system-supplied idle process)是Microsoft公司windows操作系统带有的系统进程,该进程是在各个处理器上运行的单个线程,它唯一的任务是在系统没有处理其他线程时占用处理器 时间
  • System Idle Process并不是一个真正的进程,它是核心虚拟出来的,多任务操作系统都存在。
  • 在没有可用的进程时,系统处于空运行状态,此时就是System Idle Process在正在运行。
  • 你可以简单 的理解成,它代表的是CPU的空闲状态,数值越大代表处理器越空闲,可以通过Windows任务管理 器查看Windows中的CPU利用率
    在这里插入图片描述
  • 第三种情况是,当进程阻塞在I/O、信号量或其他原因时,必须选择另外一个进程来运行。有时,阻塞 的原因会成为选择进程运行的关键因素。
  • 例如,如果A是一个重要进程,并且它正在等待B退出关键 区域,让B退出关键区域从而使A得以运行。但是调度程序一般不会对这种情况进行考量。
  • 第四点,当I/O中断发生时,可以做出调度决策。如果中断来自I/O设备,而I/O设备已经完成了其工作,那么那些等待I/O的进程现在可以继续运行。由调度程序来决定是否准备运行新的进程还是重新运 行已经中断的进程。

如果硬件时钟以50或60 Hz或其他频率提供周期性中断,可以在每个时钟中断或第k个时钟中断处做 出调度决策

根据如何处理时钟中断可以把调度算法可以分为两类:

  • 非抢占式(nonpreemptive)调度算法挑选一个进程,让该进程运行直到被阻塞(阻塞在I/O上或等待另一个进程),或者直到该进程自 动释放CPU

  • 即使该进程运行了若干个小时后,它也不会被强制挂起。这样会在时钟中断发生时不会 进行调度。

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

  • 另外一种情况是抢占式调度算法,它会选择一个进程,并使其在最大固定时间内运行。

  • 如果在时间间 隔结束后仍在运行,这个进程会被挂起,调度程序会选择其他进程来运行(前提是存在就绪进程)。

  • 进 行抢占式调度需要在时间间隔结束时发生时钟中断,以将CPU的控制权交还给调度程序。如果没有可 用的时钟,那么非抢占式就是唯一的选择

调度算法的分类

毫无疑问,不同的环境下需要不同的调度算法。之所以出现这种情况,是因为不同的应用程序和不同的 操作系统有不同的目标。

也就是说,在不同的系统中,调度程序的优化也是不同的。这里有必要划分出 三种环境

  • •批处理(Batch)

  • •交互式(Interactive)

  • •实时(Real time)

  • 批处理系统广泛应用于商业领域,比如用来处理工资单、存货清单、账目收入、账目支出、利息计算、 索赔处理和其他周期性作业。

  • 批处理系统中,一般会选择使用非抢占式算法或者周期性比较长的抢占 式算法。这种方法可以减少线程切换因此能够提升性 能。

  • 在交互式用户环境中,为了避免一个进程霸占CPU拒绝为其他进程服务,所以需要抢占式算法。

  • 即使 没有进程有意要一直运行下去,但是,由于某个进程出现错误也有可能无限期的排斥其他所有进程。为 了避免这种情况,抢占式也是必须的。

  • 服务器也属于此类别,因为它们通常为多个(远程)用户提供服 务,而这些用户都非常着急。计算机用户总是很忙。

  • 在实时系统中,抢占有时是不需要的,因为进程知道自己可能运行不了很长时间,通常很快的做完自己 的工作并阻塞。

  • 实时系统与交互式系统的差别是,实时系统只运行那些用来推进现有应用的程序,而交 互式系统是通用的,它可以运行任意的非协作甚至是有恶意的程序。

调度算法的目标

为了设计调度算法,有必要考虑一下什么是好的调度算法。

有一些目标取决于环境(批处理、交互式或 者实时)蛋大部分是适用于所有情况的

下面是一些需要考量的因素,我们会在下面一起讨论。
在这里插入图片描述

  • 在所有的情况中,公平是很重要的。对一个进程给予相较于其他等价的进程更多的CPU时间片对其 他进程来说是不公平的。当然,不同类型的进程可以采用不同的处理方式。
  • 与公平有关的是系统的强制执行,什么意思呢?
  • 如果某公司的薪资发放系统计划在本月的15号,那么碰上了疫情大家生活都很拮据,此时老板说要在14号晚上发放薪资,那么调度程序必须强制使进程执行 14号晚上发放薪资的策略。
  • 另一个共同的目标是保持系统的所有部分尽可能的忙碌。如果CPU和所有的I/O设备能够一直运行, 那么相对于让某些部件空转而言,每秒钟就可以完成更多的工作。
  • 例如,在批处理系统中,调度程序控 制哪个作业调入内存运行。
  • 在内存中既有一些CPU密集型进程又有一些I/O密集型进程是一个比较好的想法,好于先调入和运行所有的CPU密集型作业,然后在它们完成之后再调入和运行所有I/O密集型作业的做法。
  • 使用后者这种方式会在CPU密集型进程启动后,争夺CPU ,而磁盘却在空转,而当I/O密集型进程启动后,它们又要为磁盘而竞争,CPU却又在空转。。。。。。
  • 显然,通过结合I/O密集型和CPU密集型,能够使整个系统运行更流畅,效率更高。
  • 批处理系统
  • 通常有三个指标来衡量系统工作状态:吞吐量、周转时间和CPU利用率,吞吐量(throughout)是 系统每小时完成的作业数量

综合考虑,每小时完成50个工作要比每小时完成40个工作好。

  • 周转时 间(Turnaround time)是一种平均时间,它指的是从一个批处理提交开始直到作业完成时刻为止平均 时间。该数据度量了用户要得到输出所需的平均等待时间。周转时间越小越好
  • CPU利用率(CPU utilization)通常作为批处理系统上的指标。即使如此,CPU利用率也不是一 个好的度量指标,真正有价值的衡量指标是系统每小时可以完成多少作业(吞吐量),以及完成作业需 要多长时间(周转时间)。
  • 把CPU利用率作为度量指标,就像是引擎每小时转动了多少次来比较汽车 的性能一样。
  • 而且知道CPU的利用率什么时候接近100%要比什么什么时候要求得到更多的计算能力 要有用。
  • 交互式系统

  • 对于交互式系统,则有不同的指标。最重要的是尽量减少响应时间。这个时间说的是从执行指令开始 到得到结果的时间

  • 再有后台进程运行(例如,从网络上读取和保存E-mail文件)的个人计算机上, 用户请求启动一个程序或打开一个文件应该优先于后台的工作。
  • 能够让所有的交互式请求首先运行的就 是一个好的服务。
  • 一个相关的问题是 均衡性(proportionality),用户对做一件事情需要多长时间总是有一种固定 (不过通常不正确)的看法。
  • 当认为一个请求很复杂需要较多时间时,用户会认为很正常并且可以接受,但是一个很简单的程序却花费了很长的运行时间,用户就会很恼怒。
  • 可以拿彩印和复印来举出一个 简单的例子,彩印可能需要1分钟的时间,但是用户觉得复杂并且愿意等待一分钟,相反,复印很简单 只需要5秒钟,但是复印机花费1分钟却没有完成复印操作,用户就会很焦躁。
  • 实时系统

实时系统则有着和交互式系统不同的考量因素,因此也就有不同的调度目标。

  • 实时系统的特点是必须满 足最后的截止时间。
  • 例如,如果计算机控制着以固定速率产生数据的设备,未能按时运行的话可能会导 致数据丢失。
  • 因此,实时系统中最重要的需求是满足所有(或大多数)时间期限
  • 在一些实事系统中,特别是涉及到多媒体的,可预测性很重要。偶尔不能满足最后的截止时间不重要, 但是如果音频多媒体运行不稳定,声音质量会持续恶化。
  • 视频也会造成问题,但是耳朵要比眼睛敏感很 多。

为了避免这些问题,进程调度必须能够高度可预测的而且是有规律的。

2.批处理中的调度

现在让我们把目光从一般性的调度转换为特定的调度算法。

下面我们会探讨在批处理中的调度。

先来先服务

很像是先到先得。。。

  • 可能最简单的非抢占式调度算法的设计就是 先来先服务(first-come,first-serverd)。使用此算法,将按照请求顺序为进程分配CPU
  • 最基本的,会有一个就绪进程的等待队 列。当第一个任务从外部进入系统时,将会立即启动并允许运行任意长的时间。它不会因为运行时间太 长而中断
  • 当其他作业进入时,它们排到就绪队列尾部当正在运行的进程阻塞,处于等待队列的第一 个进程就开始运行
  • 当一个阻塞的进程重新处于就绪态时,它会像一个新到达的任务,会排在队列的末 尾,即排在所有进程最后
    在这里插入图片描述
  • 这个算法的强大之处在于易于理解和编程,在这个算法中,一个单链表记录了所有就绪进程。
  • 选取一 个进程运行,只要从该队列的头部移走一个进程即可;要添加一个新的作业或者阻塞一个进程,只要把 这个作业或进程附加在队列的末尾即可。

这是很简单的一种实现。

  • 不过,先来先服务也是有缺点的,那就是没有优先级的关系
  • 试想一下,如果有100个I/O进程正在排 队,第101个是一个CPU密集型进程,那岂不是需要等100个I/O进程运行完毕才会等到一个CPU 密集型进程运行
  • 这在实际情况下根本不可能,所以需要优先级或者抢占式进程的出现来优先选择重要 的进程运行。

最短作业优先

  • 批处理中,第二种调度算法是最短作业优先(Shortest Job First)

  • 我们假设运行时间已知。例 如,一家保险公司,因为每天要做类似的工作,所以人们可以相当精确地预测处理1000个索赔的一批 作业需要多长时间。

  • 当输入队列中有若干个同等重要的作业被启动时,调度程序应使用最短优先作业算法
    在这里插入图片描述

  • 如上图a所示,这里有4个作业A、B、C、D,运行时间分别为8、4、4、4分钟。

  • 若按图中的次序 运行,则A的周转时间为8分钟,B为12分钟,C为16分钟,D为20分钟,平均时间内为14分 钟。

  • 现在考虑使用最短作业优先算法运行4个作业,如上图b所示,目前的周转时间分别为4、8、12、 20,平均为11分钟,可以证明最短作业优先是最优的。

  • 考虑有4个作业的情况,其运行时间分别为 a、b、c、d。第一个作业在时间a结束,第二个在时间a + b结束,以此类推。平均周转时间为(4a + 3b + 2c + d)/4。

  • 显然a对平均值的影响最大,所以a应该是最短优先作业,其次是b,然后是c , 最后是d它就只能影响自己的周转时间了。

  • 需要注意的是,在所有的进程都可以运行的情况下,最短作业优先的算法才是最优的

最短剩余时间优先

  • 最短作业优先的抢占式版本被称作为最短剩余时间优先(Shortest Remaining Time Next)算法。

  • 使用这个算法,调度程序总是选择剩余运行时间最短的那个进程运行

  • 当一个新作业到达时,其整个时 间同当前进程的剩余时间做比较。如果新的进程比当前运行进程需要更少的时间,当前进程就被挂起, 而运行新的进程

  • 这种方式能够使短期作业获得良好的服务

未完。。。

猜你喜欢

转载自blog.csdn.net/wolfGuiDao/article/details/107738003