测试操作系统

操作系统王道考研复习——第二章(进程管理) 上

由于这一章内容比较多,所以分成上下篇

2 进程管理

2.1 程序执行

2.1.1 程序顺序执行的特征

  1. 顺序性:指处理机严格地按照程序所规定的顺序执行,即每一操作必须在下一个操作开始之前结束。
  2. 封闭性:即程序运行时独占全机资源,资源的状态(除初始状态外)只有本程序才能改变它,程序一旦开始执行,其执行结果不受外界因素影响。
  3. 可再现性:指只要程序执行时的环境和初始条件相同,当程序重复执行时,不论它是从头到尾不停顿地执行,还是“走走停停”地执行,都可获得相同的结果。

2.1.2 程序并行执行的特征

  1. 间断性:程序在并发执行时,由于它们共享系统资源,以及为完成同一项任务而相互合作,致使在这些并发执行的程序之间形成了相互制约的关系。
  2. 失去封闭性:当系统中存在着多个可以并发执行的程序时,系统中的各种资源将为它们所共享,致使其中任一程序在运行时,其他环境都必然会受到其他程序的影响。
  3. 不可再现性:程序在并发执行时,由于失去了封闭性,也将导致其又失去可再现性。

程序在并发执行时,由于失去了封闭性,其计算结果必将与并发程序的执行速度有关,从而使程序的执行失去了可再现性。换言之,程序经过多次执行后,虽然它们执行时的环境和初始条件相同,但得到的结果却各不相同。

2.2 进程与线程

2.2.1 进程的概念和特征

多道程序环境下,程序的执行属于并发执行,此时它们将失去其封闭性,并具有间断性,以及其运行结果不可再现性的特征,所以,通常的程序是不能参与并发执行的。为了能使程序并发执行,并对并发执行的程序加以描述和控制,引入了“进程”的概念。引入进程的目的是为了使其进程实体能和其他进程实体并发执行,实现操作系统的并发性和共享性(最基本的两个特征)。

进程是一个具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。它不只是程序的代码本身,还包括当前的活动,通过程序计数器的值和处理寄存器的内容来表示。

1. 程序和进程的区别:

程序:是静态的,就是个存放在磁盘里的可执行文件。
进程:是动态的,是程序的一次执行过程。
同一个程序多次执行会对应多个进程。

2. 进程的组成——PCB、程序段、数据段

为了使参与并发执行的每个程序(含数据)都能独立地运行,在操作系统中必须为之配置一个专门的数据结构,称为进程控制块(PCB)。当进程被创建时,操作系统会为该进程分配一个唯一的、不重复的“身份证号”—— PID(Process ID,进程ID)。操作系统区分各个进程就是通过PID以及进程所属用户ID(UID)来区分的。所以操作系统要记录PID、UID,还要记录给进程分配了哪些资源(如:分配了多少内存、正在使用哪些I/O设备、正在使用哪些文件),还要记录进程的运行情况(如:CPU使用时间、磁盘使用情况、网络流量使用情况等)。这些信息都被保存在PCB中。操作系统需要对各个并发运行的进程进行管理,但凡管理时所需要的信息,都会被放在PCB中。操作系统就是利用PCB来描述进程的基本情况和活动过程,进而控制和管理进程。PCB是进程存在的唯一标志
在这里插入图片描述

由程序段、相关的数据段和PCB三部分便构成了进程实体(又称进程映像)。
在这里插入图片描述
在这里插入图片描述

由上可知,PCB是给操作系统用的,程序段和数据段才是给进程自己用的。所谓创建进程,实质上是创建进程映像中的PCB,而撤销进程,实质上是撤销进程的PCB。注意:进程映像是静态的,进程则是动态的

从不同角度,进程可以有不同的定义,比较典型的定义有:

  • ①进程是程序的一次执行过程。
  • ②进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
  • ③进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。

引入进程实体后,我们可以把传统操作系统中的进程定义为:“进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。”

要注意这里说的系统资源是指处理机、存储器和其他设备服务于某个进程的“时间”,例如把处理机资源理解为处理机的时间片才是准确的。因为进程是这些资源分配和调度的独立单位,即“时间片”分配的独立单位,这就决定了进程一定是一个动态的、过程性的概念。

3. 进程的特征

进程是由多道程序的并发执行而引出的,和程序是两个截然不同的概念。它拥有以下特征:

  • 动态性:进程是程序的一次执行,它有着创建、活动、暂停、终止等过程,具有一定的生命周期,是动态地产生、变化和消亡的。动态性是进程最基本的特征
  • 并发性:指多个进程实体同时存于内存中,能在一段时间内运行。并发性是进程的重要特征,同时也是操作系统的重要特征。引入进程的目的就是是程序能与其他进程的程序并发执行,以提高资源利用率。
  • 独立性:指进程实体是一个能独立运行、独立获得资源和独立接受调度的基本单位。凡未建立PCB的程序,都不能作为一个独立的单位参与运行。
  • 异步性:由于进程的相互制约,使得进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进。异步性会导致执行结果的不可再现性,所以在操作系统中必须配置相应的=进程同步机制
  • 结构性:每个进程都配置一个PCB对其进行描述。

2.2.2 进程的状态与转换

1. 进程的三种基本状态

由于多个进程在并发执行时共享系统资源,致使它们在运行过程中呈现间断性的运行规律,所以进程在其生命周期内可能具有多种状态。一般而言,每个进程至少应处于以下三种基本状态之一:

  • 就绪态。进程获得了除处理机外的一切所需资源,一旦得到处理机,便可立即运行。系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。(其他资源✅ CPU❌)
  • 执行态。进程正在处理机上运行。在单处理机环境下,每个时刻最多只有一个进程处于运行态。而在多处理机系统中,则有多个进程处于执行状态。(其他资源✅ CPU✅)
  • 阻塞态。又称等待态或封锁态。指正在执行的进程由于发生某事件(如I/O请求、申请缓冲区失败等)暂时无法继续执行时的状态,亦即进程的执行受到阻塞。此时引起进程调度,OS把处理机分配给另一个就绪进程,而让受阻进程处于暂停状态,这种暂停状态称为阻塞态。通常系统将处于阻塞态的进程也排成一个队列,称该队列为阻塞队列。实际上,在较大的系统中,为了减少队列操作的开销,提高系统效率,根据阻塞原因的不同,会设置多个阻塞队列。(其他资源❌ CPU❌)

在这里插入图片描述

注意:区别就绪态和阻塞态。就绪态是指进程仅缺少处理机,只要获得处理机资源就立即运行;而阻塞态是指进程需要其他资源(除了处理机)或等待某一事件。之所以把处理机和其他资源划分开,是因为在分时系统的时间片轮转机制中,每个进程分到的时间片是若干毫秒。也就是说,进程得到处理机的时间很短且非常频繁,进程在运行过程中实际上是频繁地转换到就绪态的;而其他资源(如外设)的使用和分配或某一事件的发生(如I/O操作的完成)对应的时间相对来说很长,进程转换到等待态的次数也相对较少。

2. 创建状态和终止状态

为了满足进程控制块(PCB)对数据及操作的完整性要求以及增强管理的灵活性,通常在系统中又引入了两种常见的状态。

  • 创建态。进程正在被创建,尚未转到就绪态。创建进程通常需要多个步骤:首先申请一个空白的PCB,并向PCB中填写一些控制和管理进程的信息;然后又系统为该进程分配运行时所必需的资源;最后把该进程转入就绪态。
  • 结束态。进程正从系统中消失,可能是进程正常结束或其他原因中断退出运行。进程需要结束运行时,系统首先必须将该进程置为结束态,然后进一步处理资源释放和回收等。

进程PCB中,会有一个变量 state 来表示进程的当前状态。如:1表示创建态、2表示就绪态、3表示运行态…为了对同一个状态下的各个进程进行统一的管理,操作系统会将各个进程的PCB组织起来。

进程五种状态的转换如下图:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
进程PCB中,会有一个变量 state 来表示进程的当前状态。如:1表示创建态、2表示就绪态、3表示运行态…为了对同一个状态下的各个进程进行统一的管理,操作系统会将各个进程的PCB组织起来。

3. 挂起操作和进程状态的转换

在许多系统中,进程除了就绪、执行和阻塞三种最基本的状态外,为了系统和用户观察和分析进程的需要,还引入了一个对进程的重要操作——挂起操作。当该操作作用于某个进程时,该进程将被挂起,意味着此时该进程处于静止状态。如果进程正在执行,它将暂停执行。若原本处于就绪状态,则该进程此时暂不接受调度。与挂起操作对应的操作是激活操作

  1. 正在执行的进程挂起后,暂停执行。
  2. 就绪状态的进程挂起后不接受调度。
  3. 阻塞进程挂起后不能直接转换为就绪(需先激活)。

挂起操作的引入是基于系统和用户的如下需要:

  • ①终端用户的需要。当终端用户在自己的程序运行期间发现有可疑问题,希望暂停自己的程序的运行,使之停止下来,以便用户研究其执行情况或对程序进行修改。
  • ②父进程请求。有时父进程希望挂起自己的某个子进程,以便考查和修改该子进程,或者协调各子进程间的活动。
  • ③负荷调节的需要。当实时系统中的工作负荷较重,已可能影响到对实时任务的控制时,可由系统把一些不重要的进程挂起,以保证系统能正常运行。
  • ④操作系统的需要。操作系统有时希望挂起某些进程,以便检查运行中的资源使用情况或进行记账。

挂起和阻塞态的区别
挂起:由系统或程序发出,移至辅存中去。(不释放CPU,可能释放内存,移到外存去)
阻塞态:在抢占资源中得不到资源,被动的挂起在内存,等待某种资源或信号量将它唤醒。(释放CPU,不释放内存)

加入挂起和阻塞态后的进程状态图:
在这里插入图片描述
其中,创建→活动就绪:在当前系统的性能和内存的容量均允许的情况下,完成对进程创建的必要操作后,相应的系统进程将进程的状态转换为活动就绪状态。

创建→静止就绪:考虑到系统当前资源状况和性能的要求,不分配给新建进程所需资源,主要是内存,相应的系统将进程状态转为静止就绪状态,被安置在外存,不参与调度,此时进程创建工作尚未完成。

4. 进程管理中的数据结构

在计算机系统中,对于每个资源和每个进程都设置了一个数据结构,用于表征某实体,我们称之为资源信息表或进程信息表,其中包含了资源或进程的标识、描述、状态等信息以及一批指针。OS管理的这些数据结构一般分为以下四类:内存表、设备表、文件表和用于进程管理的进程表,通常进程表又被称为进程控制块PCB

PCB作为进程实体的一部分,记录了操作系统所需的,用于描述进程的当前情况以及管理进程运行的全部信息,是操作系统中最重要的记录型数据结构。它使一个在多道程序环境下不能独立运行的程序(含数据)成为一个能独立运行的基本单位,一个能与其他进程并发执行的进程。

PCB的具体作用

  • ①作为独立运行基本单位的标志。PCB已成为进程存在于系统中的唯一标志。
  • ②能实现间断性运行方式。在多道程序环境下,程序是采用停停走走间断性的运行方式运行的。当进程因阻塞而暂停运行时,它必须保留自己运行时的CPU现场信息,再次被调度运行时,还需要恢复其CPU现场信息。在有了PCB后,系统就可将CPU现场信息保存在被中断进程的PCB中,供该进程再次被调度执行时恢复CPU现场时使用。
  • ③提供进程管理所需信息。
  • ④提供进程调度所需信息。
  • ⑤实现了其他进程的同步通信。

PCB中的信息

  • ①进程标识符。进程标识符用于唯一地标识一个进程。其中包括外部标识符(创建者提供)和内部标识符(OS设置)。
  • ②处理机状态。也称为处理机的上下文。主要由处理机中各种寄存器中的内容组成,包括通用寄存器、指令计数器、程序状态字PSW、用户栈指针等。
  • ③进程调度信息。包括进程状态、进程优先级、事件和进程调度所需的其他信息。
  • ④进程控制信息。包括程序和数据的地址、进程同步和通信机制、资源清单和链接指针。
5. 进程的组织方式
  • 线性方式。即将系统中所有的PCB都组织在一张线性表中,将该表的首地址存放在内存的一个专用区域中。该方法实现简单、开销小,但每次查找时的需要扫描整张表,因此适合数目不多的系统。
    在这里插入图片描述

  • 链接方式。即把具有相同状态进程的PCB分别通过PCB中的链接字链接成一个队列。
    在这里插入图片描述
    在这里插入图片描述

  • 索引方式。即系统根据所有进程状态的不同,建立几张索引表。
    在这里插入图片描述

在这里插入图片描述

2.2.3 进程控制

进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。在操作系统中,一般把进程控制用的程序段称为原语,用原语来实现进程控制。原语的特点是执行期间不允许中断,它是一个不可分割的基本单位

简化理解:进程控制就是要实现进程状态转换。

原语的执行具有原子性,即执行过程只能一气呵成,期间不允许被中断
在这里插入图片描述
在这里插入图片描述

可以用“关中断指令”和“开中断指令”这两个特权指令实现原子性。
在这里插入图片描述
正常情况:CPU每执行完一条指令都会例行检查是否有中断信号需要处理,如果有,则暂停运行当前这段程序,转而执行相应的中断处理程序。

CPU执行了关中断指令之后,就不再例行检查中断信号,直到执行开中断指令之后才会恢复检查,才会去执行关中断期间的外部中断程序。这样,关中断、开中断之间的这些指令序列就是不可被中断的,这就实现了“原子性”。以下都是进程控制相关的原语

1. 进程的创建

允许一个进程创建另一个进程,此时创建者称为父进程,被创建的进程称为子进程。子进程可以继承父进程所拥有的资源。当子进程被撤销时,应将其从父进程那里获得的资源归还给父进程。此外,在撤销父进程时,必须同时撤销其所有的子进程。进程的创建以及引起进程创建的事件如下图所示:
在这里插入图片描述
进程创建完成后会进入就绪队列
设备分配是通过在系统中设置相应的数据结构实现的,不需要创建进程,这是操作系统中I/O核心子系统的内容。

2. 进程的终止

在这里插入图片描述
注意是,先对其所占有的资源执行回收操作,然后再撤销PCB。

3. 进程的阻塞和唤醒

在这里插入图片描述
进程阻塞是进程自身的一种主动行为(挂起是被动的),也因此只有处于核心态的进程(拥有CPU),才可能将其转为阻塞态。阻塞原语(Block原语)和唤醒原语(Wakeup原语)是一对作用恰好相反的原语,必须成对使用

4. 进程切换

对于通常的进程而言,其创建、撤销及要求由系统设备完成的I/O操作,都是利用系统调用而进入内核,再由内核中的相应处理程序予以完成的。进程切换同样是在内核的支持下实现的,因此可以说,任何进程都是在操作系统内核的支持下运行的,是与内核紧密相关的。进程切换是指处理机从一个进程的运行转到另一个进程上运行。
在这里插入图片描述
注意,进程切换与处理机模式切换是不同的。处理机模式切换时,处理机逻辑上可能还在同一进程中运行。若进程因中断或异常进入核心态运行,执行完后又回到用户态刚被中断的程序运行,则操作系统只需恢复进程进入内核时所保存的CPU现场,而无须改变当前进程的环境信息。但若要切换进程,当前运行进程改变了,则当前进程的环境信息也需要改变。

运行环境信息称为进程的上下文;处理机状态信息称为处理机的上下文

无论哪个进程控制原语,要做的无非三类事情:

  • ①更新PCB中的信息(修改进程状态,保存/恢复运行环境)
  • ②将PCB插入合适的队列
  • ③分配/回收资源

在这里插入图片描述
在这里插入图片描述

2.2.4 进程的组织

进程是一个独立的运行单位,也是操作系统进行资源分配和调度的基本单位。它由以下三部分组成,其中最核心的是进程控制块(PCB)。

  1. 进程控制块
    进程创建时,操作系统为它新建一个PCB,该结构之后常驻内存,任意时刻都可以存取,并在进程结束时删除。PCB是进程实体的一部分,也是进程存在的唯一标志。

    进程执行时,系统通过其PCB了解进程的现行状态信息,以便对其进行控制和管理;进程结束时,系统收回其PCB,该进程随之消亡。操作系统通过PCB表来管理和控制进程。

    在进程的整个生命期中,系统总是通过PCB对进程进行控制的,亦即系统唯有通过进程的PCB才能感知到该进程的存在。

  2. 程序段
    程序段就是能被进程调度程序调度到CPU执行的程序代码段。注意:程序可被多个进程共享,即多个进程可以运行同一个程序。

  3. 数据段
    一个进程的数据段,可以是进程对应的程序加工处理的原始数据,也可以是程序执行时产生的中间或最终结果。

2.2.5 进程的通信

进程通信是指进程之间的信息交换。进程通信需要操作系统支持,因为进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。
在这里插入图片描述
为了保证安全,一个进程不能直接访问另一个进程的地址空间。

PV操作是低级通信方式,高级通信方式是指以较高的效率传输大量数据的通信方式。高级通信方式方法主要有以下三类。

1. 共享存储

在通信的进程之间存在一块可直接访问的共享空间,通过对这片共享空间进行写/读操作实现进程之间的信息交换。
在这里插入图片描述
注:通过“增加页表项/段表项”即可将同一片共享内存区映射到各个进程的地址空间中(第三章内容)。用户进程空间一般都是独立的,进程运行期间一般不能访问其他进程的空间,要想让两个用户进程共享空间,必须通过特殊的系统调用实现,而进程内的现场是自然共享进程空间的。

为避免出错,各个进程对共享空间的访问应该是互斥的。各个进程可使用操作系统内核提供的同步互斥工具(如P、V操作)。操作系统只负责为通信进程提供可共享使用的存储空间和同步互斥工具,而数据交换则由用户自己安排读/写指令完成。

  1. 基于数据结构的共享
    在这里插入图片描述
    比如共享空间里只能放一个长度为10的数组。这种共享方式仅适用于传递相对少量的数据,速度慢、限制多,是一种低级通信方式。

  2. 基于存储区的共享
    在这里插入图片描述

    操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信方式。

2. 消息传递(最广泛的使用方式)

进程间的数据交换以格式化的消息(Message)为单位(不同环境下,消息格式不同)。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。若通信的进程之间不存在可直接访问的共享空间,则必须利用操作系统提供的消息传递方式实现进程通信。

在计算机网络中,消息又称为报文;在微内核与服务器之间的通信也都是采用了消息传递机制。

基于消息传递的通信方式属于高级通信方式,因其实现方式的不同,可进一步分为两类:
在这里插入图片描述

  1. 直接通信方式(点名道姓的消息传递)
    发送进程直接把消息发送给接收进程,并将它挂在接收进程的消息缓冲队列上,接收进程从消息缓冲队列中取得消息。
    在这里插入图片描述
    注:由于PCB是保存在操作系统内核中,所以消息队列也是在内核中。
  2. 间接通信方式(以“信箱”作为中间实体进行消息传递)
    发送进程把消息发送到某个中间实体,接收进程从中间实体取得消息。这种中间实体一般称为信箱,这种通信方式又称信箱通信方式。该通信方式广泛应用于计算机网络中,相应的通信系统称为电子邮件系统。
    在这里插入图片描述
3. 管道通信

在这里插入图片描述

  1. 管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道。
  2. 各进程要互斥地访问管道(由操作系统实现)。
  3. 当管道写满时,写进程将阻塞,直到读进程将管道中的数据取走,即可唤醒写进程。
  4. 当管道读空时,读进程将阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
  5. 管道中的数据一旦被读出,就彻底消失。因此,当多个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:①一个管道允许多个写进程,一个读进程(2014年408真题高教社官方答案);②允许有多个写进程,多个读进程,但系统会让各个读进程轮流从管道中读数据(Linux 的方案)。
  6. 向管道(共享文件)提供输入的发送进程(即写进程),以字节流形式将大量的数据送入(写)管道;而接收管道输出的接收进程(即读进程)则从管道中接收(读)数据。为了协调双方的通信,管道机制必须提供三方面的协调能力:互斥同步确定对方的存在
  7. 写进程往管道写数据,即便管道没被写满,只要管道没空,读进程就可以从管道读数据。读进程从管道读数据,即便管道没被读空,只要管道没满,写进程就可以往管道写数据。
  8. 从管道读取数据是一次性操作,数据一旦被读取,它就从管道中被抛弃,释放空间以便写更多的数据,管道只能采用半双工通信,即某一时刻只能单向传输,要实现父子进程双方互动通信,需要定义两个管道。
  9. 管道的底层数据结构是一个循环队列。

在这里插入图片描述

2.2.6 线程概念和多线程模型

1. 线程的引入

还没引入进程之前,系统中各个程序只能串行执行。
在这里插入图片描述
在这里插入图片描述
如果说,在OS中引入进程的目的是为了使多个程序能并发执行,以提高资源利用率和系统吞吐量,那么,在OS中引入线程,则是为了减少程序在并发执行时所付出的时空开销,使OS具有更好的并发性,增加了并发度

2. 线程的基本概念

线程最直接的理解就是“轻量级进程”(LWP),它是一个基本的CPU执行单元,也是程序执行流的最小单元,由线程ID、程序计数器、寄存器集合和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。

一个线程可以创建和撤销另一个线程,同个进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。

引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务(如QQ视频、文字聊天、传文件等可以并发执行)。引入线程后,进程只作为除CPU之外的系统资源的分配单元(如打印机、内存地址空间等都是分配给进程的)。线程则作为处理机的分配单元。

3. 线程与进程的比较
  1. 调度:在传统的OS中,进程是资源分配、调度的基本单位。引入线程后,进程是资源分配的基本单位,线程是调度的基本单位。在同一进程中,线程的切换不会引起进程切换。在不同进程中进行线程切换,如从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换。
  2. 拥有资源:不论是传统操作系统回收设有线程的操作系统,进程都是拥有资源的基本单位,而线程不拥有系统资源(只有一点必不可少的资源),但线程可以访问其隶属进程的系统资源。
  3. 并发性:在传统的OS中,只有进程间并发。在引入线程后,各线程间也能并发,提升了并发度。
  4. 系统开销:传统的进程间并发时,需要切换进程的运行环境,系统开销很大。而线程间并发时,如果是同一进程内的线程切换,则不需要切换进程环境,系统开销小。
4. 线程的属性

多线程操作系统把线程作为独立运行(或调度)的基本单位,此时的进程已不再是一个基本的可执行实体,但它仍具有与执行相关的状态。所谓进程处于“执行”状态,实际上是指该进程中的某线程正在执行。线程的主要属性如下:

  1. 线程是处理机调度的单位
  2. 多CPU计算机中,各个线程可占用不同的CPU
  3. 每个线程都有一个线程ID、线程控制块(TCB)
  4. 线程也有就绪、阻塞、运行三种基本状态
  5. 线程几乎不拥有系统资源
  6. 同一进程的不同线程间共享进程的资源
  7. 由于共享内存地址空间,线程没有自己独立的地址空间,同一进程中的线程间通信甚至无需系统干预,可以直接通过它们共享的存储空间进行通信
  8. 同一进程中的线程切换,不会引起进程切换
  9. 切换同进程内的线程,系统开销很小
  10. 切换进程,系统开销较大
5. 线程的实现方式

线程的实现可以分为两类:用户级线程(User-Level Thread,ULT)和内核级线程(Kernel-Level Thread,KLT)。内核级线程又称内核支持的线程。(按切换时是否依赖内核进行区分)

  1. 用户级线程(ULT)
    历史背景:早期的操作系统(如:早期Unix)只支持进程,不支持线程。当时的“线程”是由线程库实现的。

    在用户级线程中,有关线程管理(线程的创建、撤销和切换等)的所有工作都由应用程序完成,内核意识不到线程的存在。应用程序可以通过使用线程库设计成多线程程序。在用户级线程的系统中,其调度仍是以进程为单位。
    在这里插入图片描述

    在这里插入图片描述
    很多编程语言提供了强大的线程库,可以实现线程的创建、销毁、调度等功能。

    1)用户级线程由应用程序通过线程库实现,所有的线程管理工作都由应用程序负责(包括线程切换)。
    2)用户级线程中,线程切换可以在用户态下即可完成,无需操作系统干预。
    3.)在用户看来,是有多个线程。但是在操作系统内核看来,并意识不到线程的存在。“用户级线程”就是“从用户视角看能看到的线程”
    4.)优缺点
    优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高。用户级线程的实现与OS无关,因为对于线程管理的代码是属于用户程序的一部分,所有的应用程序都可以对之进行共享。因此,用户级线程甚至可以在不支持线程机制的操作系统平台上实现。
    缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行,因为内核每次分配给一个进程的仅有一个CPU,因此,进程中仅有一个线程能执行,在该线程放弃CPU1之前,其他线程只能等待。

  2. 内核级线程(KLT,又称“内核支持的线程”)
    在内核级线程中,线程管理的所有工作由内核完成,应用程序没有进行线程管理的代码,只有一个到内核级线程的编程接口。内核为基础及其内部的每个线程维护上下文信息,调度也在内核基于线程架构的基础上完成,调度是以线程为单位。
    在这里插入图片描述
    1)内核级线程的管理工作由操作系统内核完成。
    2)线程调度、切换等工作都由内核负责,因此内核级线程的切换必然需要在核心态下才能完成。
    3)操作系统会为每个内核级线程建立相应的TCB(Thread Control Block,线程控制块),通过TCB对线程进行管理。“内核级线程”就是“从操作系统内核视角看能看到的线程”。
    4)优缺点
    优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。
    缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态(用户进程的线程在用户态运行,而线程调度和管理在内核实现的),因此线程管理的成本高,开销大。

总结:不论是进程还是线程,都必须直接或间接地取得内核的支持。由于内核支持线程可以直接利用系统调用为它服务,故线程的控制相当简单;而用户级线程必须借助于某种形式的中间系统的帮助才能取得内核的服务,故在对线程的控制上要稍微复杂些。

6. 多线程模型

在支持内核级线程的系统中,根据用户级线程和内核级线程的映射关系,可以划分为几种多线程模型。

  1. 一对一模型
    在这里插入图片描述
    一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。

    优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。
    缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。

  2. 多对一模型
    在这里插入图片描述
    即多个用户级线程映射到一个内核级线程。这些用户线程一般属于一个进程,运行在该进程的用户空间,对这些线程的调度和管理也是在该进程的用户空间中完成。仅当用户线程需要访问内核时,才将其映射到一个内核控制线程上,但每次只允许一个线程进行映射

    优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高。
    缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。

    重点重点重点:
    操作系统只“看得见”内核级线程,因此只有内核级线程才是处理机分配的单位。

  3. 多对多模型
    在这里插入图片描述
    n 用户及线程映射到 m 个内核级线程(n >= m)。每个用户进程对应 m 个内核级线程。

    克服了多对一模型并发度不高的缺点(一个阻塞全体阻塞),又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。

    可以这么理解:
    用户级线程是“代码逻辑”的载体。
    内核级线程是“运行机会”的载体。
    内核级线程才是处理机分配的单位。例如:多核CPU环境下,上面这个进程最多能被分配两个核。一段“代码逻辑”只有获得了“运行机会”才能被CPU执行。内核级线程中可以运行任意一个有映射关系的用户级线程代码,只有两个内核级线程中正在运行的代码逻辑都阻塞时,这个进程才会阻塞。

2.2.7 补充

  1. 每个进程包含独立的地址空间,进程各种的地址空间是私有的,只能指向自己地址空间中的程序,且只能访问自己地址空间中的数据,相互访问会导致指针的越界错误。因此,进程之间不能直接交换数据,但可利用操作系统提高的共享文件、消息传递、共享存储区等进行通信。
  2. 进程与程序的根本区别是静态和动态特点
  3. 进程调度时,优先级分静态和动态两种,动态优先级是根据运行情况而随时调整的;静态优先级则是在创建进程时确定,且在进程的整个运行期间是保持不变的。
  4. 在单处理器系统中,并不是任何时刻都只有一个进程处于运行态。因为在系统发生死锁时有可能进程全部都处于阻塞态或无进程任务。
  5. 在任何时刻,一个进程的状态变化不一定引起另一个进程的状态变化。例如,一个进程时间片用完,可能会引起另一个就绪进程的运行。但一个进程由阻塞态转变为就绪态就不会引起其他进程的状态变化。
  6. 在单处理机系统中,若同时存在10个进程,则处于就绪队列中的进程最多有9个,1个正在运行。但处于阻塞队列中的进程最多就有可能是10个。
  7. 系统进程所请求的一次I/O操作完成前,进程处于阻塞态;当I/O操作完成后,就转变为就绪态。
  8. 程序封闭性是指进程执行的结果只取决于进程本身,不受外界影响。也就是说,进程在执行过程中不管是不停顿地执行,还是走走停停,进程的执行速度都不会改变它的执行结果。失去封闭性后,不同速度下的执行结果不同。
  9. 进程在处理机上执行时,进程之间可能是无关的,有可能是有交互性的。
  10. C语言编写的程序在使用内存时一般分为三个段,它们一般时正文段(即代码和赋值数据段)、数据堆段和数据栈段。二进制代码和常量存放在正文段,动态分配的存储区在数据堆段,临时使用的变量在数据栈段。由此,可以确定全局赋值变量在正文段赋值数据段,未赋值的局部变量和实参传递在栈段,动态内存分配在堆段,常量在正文段,进程的优先级只能在PCB中。
  11. 一个进程是程序在一个数据集上的一次运行过程。运行于不同的数据集,将会形成不同的进程。
  12. 系统动态DLL库中的系统线程,被不同的进程所调用,它们是相同的进程。进程是暂时的,程序是永久的;进程至少由代码、数据和PCB组成,程序仅需代码和数据即可;程序代码经过多次创建可对应不同的进程,而同一个系统的进程(或线程)可以由系统调用的方法被不同的进程(或线程)多次使用。
  13. 全局变量与PCB无关,它只与用户代码有关。
  14. 一个计算机系统中,进程的最大数目主要受到内存大小的限制。进程创建需要占用系统内存来存放PCB的数据结构,所以一个系统能够创建的进程总数是有限的,进程的最大数目取决于系统内存的大小。
  15. 在支持多线程的系统中,进程P创建的若干线程不能共享的是进程P某线程的栈指针,因为它对其他线程是透明的。
  16. 整个系统只有一个键盘,而且键盘输入是人的操作,速度比较漫,完全可以使用一个线程来处理整个系统的键盘输入,无须利用多线程。
  17. 不同进程拥有不同的代码段和数据段,全局变量是对同一进程而言的,在不同的进程中是不同的变量,没有任何联系,所以不能用全局变量来交换数据。
  18. 引起进程从运行态转换为就绪态的事件可能是时间片用完或者是出现了比现在进程优先级更改的进程。
  19. 降低进程优先级的合理时机是进程时间片用完,因为可以让其他进程被调度进入执行状态。当进程刚完成I/O操作,进入就绪队列等待被处理机调度时,为了让其尽快处理I/O结果,就应该提高优先级。当进程长期处于就绪队列时,为了不至于产生饥饿现象,也应提高优先级。
  20. 多线程是指一个程序中可以定义多个线程并同时运行它们,每个线程可以执行不同的任务。多线程与多任务的区别:多任务是针对操作系统而言的,代表操作系统可以同时执行的程序个数;多线程是针对一个程序而言的,代表一个程序可以同时执行的线程个数,而每个线程可以完成不同的任务。
  21. 若系统中没有运行进程,则一定没有就绪进程。因为若系统中未运行进程,则系统很快会选择一个就绪进程运行,只有就绪队列中无进程时,CPU才可能处于空闲状态。
  22. 在采用优先级进程调度时,运行进程不一定是系统中优先级最高的进程。因为高优先级的进程有可能正处于等待队列中,进程调度会从就绪队列中选择一个进程占用CPU,这个被选中的进程可能优先级较低。

2.3 处理机调度

2.3.1 调度的概念

在这里插入图片描述
当有一堆任务要处理,但由于资源有限,这些事情没法同时处理。这就需要确定某种规则来决定处理这些任务的顺序,这就是“调度”研究的问题。调度的实质是一种资源分配。

一个作业从提交开始直到完成,往往要经历以下三种调度:

1. 高级调度(作业调度)

它的调度对象是作业。其主要功能是根据某种算法,决定将外存上处于后备队列中的哪几个作业调入内存,为它们创建进程、分配必要的资源,将它们放入到就绪队列。高级调度主要用于多道批处理系统中,而其他系统通常不配置作业调度,作业调度的执行效率较低,通常为几分钟一次。

对于每个作业只调入一次,调出一次。

2. 低级调度(进程调度)

它的调度对象是进程或内核级线程。按照某种策略从就绪队列中选取一个进程,将处理机分配给它。进程调度是操作系统中最基本的一种调度,在一般的操作系统中都必须配置进程调度。进程调度的频率很高,一般几十毫秒一次。

3. 中级调度(内存调度)

在这里插入图片描述

其作用是提高内存利用率和系统吞吐量。为此,应将那些暂时不能运行的进程调至外存等待,把此时的进程状态称为挂起态。当它们已具备运行条件且内存又稍有空闲时,由中级调度来决定把外存上那些已具备运行条件的就绪进程,再重新调入内存,并修改其状态为就绪态,挂在就绪队列上等待。

4. 进程的挂起态与七状态模型

暂时调到外存等待的进程状态为挂起状态(挂起态,suspend)。
挂起态又可以进一步细分为就绪挂起、阻塞挂起两种状态。
在这里插入图片描述
注意“挂起”和“阻塞”的区别,两种状态都是暂时不能获得CPU的服务,但挂起态是将进程映像调到外存去了,而阻塞态下进程映像还在内存中。 有的操作系统会把就绪挂起、阻塞挂起分为两个挂起队列,甚至会根据阻塞原因不同再把阻塞挂起进程进一步细分为多个队列。

5. 三层调度的联系和对比

在这里插入图片描述

2.3.2 调度的时机、切换与过程

1. 进程调度的时机

进程调度(低级调度),就是按照某种算法从就绪队列中选择一个进程为其分配处理机。

1)需要进行进程调度与切换的情况
  1. 当前运行的进程主动放弃处理机
    ①进程正常终止
    ②运行过程中发生异常而终止
    ③进程主动请求阻塞(如 等待I/O)
  2. 当前运行的进程被动放弃处理机
    ①分给进程的时间片用完
    ②有更紧急的事需要处理(如 I/O中断)
    ③有更高优先级的进程进入就绪队列
2)不能运行进程调度与切换的情况

①在处理中断的过程中。中断处理过程复杂,与硬件密切相关,很难做到在中断处理过程中进行进程切换。
②进程在操作系统内核程序临界区中。(注意:进程调度和切换程序都是操作系统内核程序
③在原子操作过程中(原语)。原子操作不可中断,要一气呵成(如之前讲过的修改PCB中进程状态标志,并把PCB放到相应队列就属于原子操作)

3)补充

有如下的判断题
在这里插入图片描述
临界资源:一个时间段内只允许一个进程使用的资源。各进程需要互斥地访问临界资源。
临界区:访问临界资源的那段代码。
内核程序临界区一般是用来访问某种内核数据结构的,比如进程的就绪队列(由各就绪进程的PCB组成)

当进程处于临界区时,说明进程正在占用处理机,只要不破坏临界资源的使用规则,就不会影响处理机的调度,比如访问的临界资源是慢速的外设(如打印机)。所以在访问临界区时能不能进行调度和切换还得看情况。

再通过以下两个例子,相信大家可以更加理解什么时候可以进行调度和切换:
在这里插入图片描述

在这里插入图片描述
在访问内核程序临界区期间时不能进行调度与切换;而在访问普通临界区时可以进行调度与切换。

2. 进程切换

进程切换往往在调度完成后立刻发生,它要求保存原进程当前切换点的现场信息,恢复被调度进程的现场信息。现场切换时,操作系统内核将原进程的现场信息推入当前进程的内核堆栈来保存它们,并更新堆栈指针。内核完成从新进程的内核栈中装入新机场的现场信息、更新当前运行进程空间指针、重设PC寄存器等相关工作之后,开始运行新的进程。

“狭义的进程调度”与“进程切换”的区别:
狭义的进程调度指的是从就绪队列中选中一个要运行的进程。(这个进程可以是刚刚被暂停执行的进程,也可能是另一个进程,后一种情况就需要进程切换)
进程切换是指一个进程让出处理机,由另一个进程占用处理机的过程。

广义的进程调度包含了选择一个进程和进程切换两个步骤。
进程切换的过程主要完成了:
①对原来运行进程各种数据的保存
②对新的进程各种数据的恢复(如:程序计数器、程序状态字、各种数据寄存器等处理机现场信息,这些信息一般保存在进程控制块)
注意:进程切换是有代价的=,因此如果过于频繁的进行进程调度、切换,必然会使整个系统的效率降低,使系统大部分时间都花在了进程切换上,而真正用于执行进程的时间减少。

2.3.3 进程调度方式

所谓进程调度方式,是指当某个进程正在处理机上执行时,若有某个更为重要或紧迫的基础需要处理,即有优先权更高的进程进入就绪队列,此时应如何分配处理机。通常由以下两个进程调度方式:

1. 非剥夺调度方法

非剥夺调度方式,又称非抢占方式。即,只允许进程主动放弃处理机。在运行过程中即便有更紧迫的任务到达,当前进程依然会继续使用处理机,直到该进程终止或主动要求进入阻塞态。在非剥夺调度方式下,一旦把CPU分配给一个进程,该进程就会保持CPU直到终止或转换到阻塞态。

这种方法实现简单,系统开销小但是无法及时处理紧急任务,适合于早期的批处理系统,不能用于分时系统和大多数的实时系统。

2. 剥夺调度方法

剥夺调度方式,又称抢占方式。当一个进程正在处理机上执行时,如果有一个更重要或更紧迫的进程需要使用处理机,则立即暂停正在执行的进程,将处理机分配给更重要紧迫的那个进程。

这种方法可以优先处理更紧急的进程,也可实现让各进程按时间片轮流执行的功能(通过时钟中断)。适合于分时操作系统、实时操作系统。采用剥夺式的调度,对提高系统吞吐率和响应效率都有明显的好处。但“剥夺”不是一种任意性行为,必须遵循一定的原则,主要由优先权、短进程优先和时间片原则等。

2.3.4 调度的基本准则

1. CPU利用率

由于早期的CPU造价极其昂贵,因此人们会希望让CPU尽可能多地工作。
CPU利用率:指CPU “忙碌”的时间占总时间的比例。
在这里插入图片描述

2. 系统吞吐量

对于计算机来说,希望能用尽可能少的时间处理完尽可能多的作业。
系统吞吐量:单位时间内完成作业的数量。
在这里插入图片描述

3. 周转时间

周转时间,是指从作业被提交给系统开始,到作业完成为止的这段时间间隔。
它包括四个部分:作业在外存后备队列上等待作业调度(高级调度)的时间、进程在就绪队列上等待进程调度(低级调度)的时间、进程在CPU上执行的时间、进程等待I/O操作完成的时间。后三项在一个作业的整个处理过程中,可能发生多次。
在这里插入图片描述
有的作业运行时间短,有的作业运行时间长,因此在周转时间相同的情况下,运行时间不同的作业,给用户的感觉肯定是不一样的。所以有了带权周转时间

4. 带权周转时间

在这里插入图片描述
对于周转时间相同的两个作业,实际运行时间长的作业在相同时间内被服务的时间更多,带权周转时间更小,用户满意度更高
对于实际运行时间相同的两个作业,周转时间短的带权周转时间更小,用户满意度更高。

5. 等待时间

等待时间,指进程/作业处于等待处理机状态时间之和,等待时间越长,用户满意度越低。
在这里插入图片描述
对于进程来说,等待时间就是指进程建立后等待被服务的时间之和,在等待I/O完成的期间其实进程也是在被服务的,所以不计入等待时间。
对于作业来说,不仅要考虑建立进程后的等待时间,还要加上作业在外存后备队列中等待的时间

一个作业总共需要被CPU服务多久,被I/O设备服务多久一般是确定不变的,因此调度算法其实只会影响作业/进程的等待时间。当然,与前面指标类似,也有“平均等待时间”来评价整体性能。

6. 响应时间

对于计算机用户来说,会希望自己的提交的请求(比如通过键盘输入了一个调试命令)尽早地开始被系统服务、回应。
响应时间,指从用户提交请求首次产生响应所用的时间。

2.3.5 典型的调度算法

操作系统中存在多种调度算法,有的调度算法适用于作业调度,有的调度算法适用于进程调度,有的调度算法两者都适用。下面首先介绍一下作业的概念。

1. 作业的概念

在多道批处理系统中,作业是用户提交给系统的一项相对独立的工作。操作员把用户提交的作业通过相应的输入设备输入到磁盘存储器,并保存在一个后备作业队列中。再由作业调度程序将其从外存调入内存

作业是一个比程序更为广泛的概念,它不仅包含了通常的程序和数据,而且还应配有一份作业说明书,系统根据该说明书来对程序的运行进行控制。在批处理系统中,是以作业为基本单位从外存调入内存的。

作业从进入系统到运行结束,通常需要经历收容、运行和完成三个阶段。相应的作业也就有“提交状态”、“后备状态”、“运行状态”和“完成状态”。

下面介绍一下调度算法:

2. 先来先服务(FCFS, First Come First Serve)

FCFS调度算法是一种最简单的调度算法,它既可用于作业调度,又可用于进程调度。在作业调度中,算法每次从后备作业队列中选择最先进入该队列的一个或几个作业,将它们调入内存,分配必要的资源,创建进程并放入就绪队列。在进程调度中,FCFS调度算法每次从就绪队列中选择最先进入该队列的进程,将处理机分配给它,使之投入运行,直到完成或因某种原因而阻塞时才释放处理机。

  1. 算法思想: 主要从“公平”的角度考虑(类似于我们生活中排队买东
    西的例子)
  2. 算法规则: 按照作业/进程到达的先后顺序进行服务,或者说它是优先考虑在系统中等待时间最长的作业。
  3. 用于作业/进程调度: 用于作业调度时,考虑的是哪个作业先到达后备队列;用于进程调度时,考虑的是哪个进程先到达就绪队列
  4. 是否可抢占? 非抢占式的算法
  5. 优缺点: 优点:公平、算法实现简单。缺点:排在长作业(进程)后面的短作业需要等待很长时间,带权周转时间很大,对短作业来说用户体验不好。即,FCFS算法对长作业有利,对短作业不利
  6. 是否会导致饥饿(某进程/作业长期得不到服务): 不会

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用先来先服务调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。
在这里插入图片描述
在这里插入图片描述

3. 短作业优先(SJF, Shortest Job First)

短作业优先(SJF)调度算法从后备队列中选择一个或者若干估计运行时间最短的作业,将它们调入内存运行;短进程优先(SPF)调度算法从就绪队列中选择一个估计运行时间最短的进程,将处理机分配给它,使之立即执行,直到完成或发生某事件而阻塞时,才释放处理机。

  1. 算法思想: 追求最少的平均等待时间,最少的平均周转时间、最少的平均带权周转时间
  2. 算法规则: 最短的作业/进程优先得到服务(所谓“最短”,是指要求服务时间最短)
  3. 用于作业/进程调度: 即可用于作业调度,也可用于进程调度。用于进程调度时称为“短进程优先(SPF, Shortest Process First)算法”
  4. 是否可抢占? SJF和SPF是非抢占式的算法。但是也有抢占式的版本——最短剩余时间优先算法(SRTN, Shortest Remaining Time Next)
  5. 优缺点: 优点:“最短的”(这里的最短的是得看条件的)平均等待时间、平均周转时间。缺点:不公平。对短作业有利,对长作业不利。可能产生饥饿现象。另外,作业/进程的运行时间是由用户提供(用户估计的)的,并不一定真实,不一定能做到真正的短作业优先。
  6. 是否会导致饥饿: 会。如果源源不断地有短作业/进程到来,可能使长作业/进程长时间得不到服务,产生“饥饿”现象。如果一直得不到服务,则称为“饿死”。

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用非抢占式的短作业优先调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。
在这里插入图片描述
在这里插入图片描述

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用抢占式的短作业优先调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。(抢占式的短作业优先算法又称“最短剩余时间优先算法(SRTN)”)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意几个小细节

  1. 如果题目中未特别说明,所提到的“短作业/进程优先算法”默认是非抢占式的
  2. 很多书上都会说“SJF 调度算法的平均等待时间、平均周转时间最少”。
    严格来说,这个表述是错误的,不严谨的。之前的例子表明,最短剩余时间优先算法得到的平均等待时间、平均周转时间还要更少。
    应该加上一个条件“在所有进程同时可运行时,采用SJF调度算法的平均等待时间、平均周转时间最少”;或者说“在所有进程都几乎同时到达时,采用SJF调度算法的平均等待时间、平均周转时间最少”;
    如果不加上述前提条件,则应该“抢占式的短作业/进程优先调度算法(最短剩余时间优先, SRNT算法)的平均等待时间、平均周转时间最少”
  3. 虽然严格来说,SJF的平均等待时间、平均周转时间并不一定最少,但相比于其他算法(如 FCFS),SJF依然可以获得较少的平均等待时间、平均周转时间。
  4. 如果选择题中遇到“SJF 算法的平均等待时间、平均周转时间最少”的选项,那最好判断其他选项是不是有很明显的错误,如果没有更合适的选项,那也应该选择该选项。
4. 高响应比优先(HRRN, Highest Response Ratio Next)

在批处理系统中,FCFS算法所考虑的只是作业的等待时间,而忽视了作业的运行时间。而SJF算法正好与之相反,只考虑作业的运行时间,而忽视了作业的等待时间,又考虑作业运行时间的调度算法,因此既照顾了短作业,又不致使长作业的等待时间过长,从而改善了处理机调度的性能。

  1. 算法思想: 要综合考虑作业/进程的等待时间和要求服务的时间
  2. 算法规则: 在每次调度时先计算各个作业/进程的响应比,选择响应比最高的作业/进程为其服务。
    在这里插入图片描述
  3. 用于作业/进程调度: 即可用于作业调度,也可用于进程调度
  4. 是否可抢占? 非抢占式的算法。因此只有当前运行的作业/进程主动放弃处理机时,才需要调度,才需要计算响应比。
  5. 优缺点: 优点:综合考虑了等待时间和运行时间(要求服务时间)等待时间相同时,要求服务时间短的优先(SJF 的优点);要求服务时间相同时,等待时间长的优先(FCFS 的优点);对于长作业来说,随着等待时间越来越久,其响应比也会越来越大,从而避免了长作业饥饿的问题。缺点:每次要进行调度之前,都需要先做响应比的计算,显然会增加系统开销
  6. 是否会导致饥饿: 不会

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用高响应比优先调度算法,计算各进程的等待时间、平均等待时间、周转时间、平均周转时间、带权周转时间、平均带权周转时间。
在这里插入图片描述
在这里插入图片描述

小结:
在这里插入图片描述
注:这几种算法主要关心对用户的公平性、平均周转时间、平均等待时间等评价系统整体性能的指标,但是不关心“响应时间”,也并不区分任务的紧急程度,因此对于用户来说,交互性很糟糕。因此这三种算法一般适合用于早期的批处理系统,当然,FCFS算法也常结合其他的算法使用,在现在也扮演着很重要的角色。而适合用于交互式系统的调度算法将在下面介绍。

5. 时间片轮转(RR, Round-Robin)

时间片轮转调度算法主要适用于分时系统,更加注重“响应时间”。

  1. 算法思想: 公平地、轮流地为各个进程服务,让每个进程在一定时间间隔内都可以得到响应。
  2. 算法规则: 按照各进程到达就绪队列的顺序,轮流让各个进程执行一个时间片(如 100ms)。若进程未在一个时间片内执行完,则剥夺处理机,将进程重新放到就绪队列队尾重新排队。
  3. 用于作业/进程调度: 用于进程调度(作业要先放入内存建立了相应的进程后,才能被分配处理机时间片,所以没有作业调度)。
  4. 是否可抢占? 若进程未能在时间片内运行完,将被强行剥夺处理机使用权,因此时间片轮转调度算法属于抢占式的算法。由时钟装置发出时钟中断来通知CPU时间片已到。
  5. 优缺点: 优点:公平;响应快,适用于分时操作系统;缺点:由于高频率的进程切换,因此有一定开销;不区分任务的紧急程度。
  6. 是否会导致饥饿: 不会
  7. 补充: 若选择很小的时间片,将有利于短作业,因为它能在该时间片内完成。但时间片小,意味着会频繁地执行进程调度和进程上下文的切换,这无疑会增加系统的开销。反之,若时间片选择得太长,且为使每个进程都能在一个时间片内完成,RR算法便退化为FCFS算法,无法满足短作业和交互式用户的需求。

例题:各进程到达就绪队列的时间、需要的运行时间如下表所示。使用时间片轮转调度算法,分析时间片大小分别是2、5时的进程运行情况。
在这里插入图片描述
时间片大小为 2 时(注:以下括号内表示当前时刻就绪队列中的进程、进程的剩余运行时间)
0时刻(P1(5)):0时刻只有P1到达就绪队列,让P1上处理机运行一个时间片.
2时刻(P2(4) → P1(3)):2时刻P2到达就绪队列,P1运行完一个时间片,被剥夺处理机,重新放到队尾。此时P2排在队头,因此让P2上处理机。(注意: 2时刻,P1下处理机,同一时刻新进程P2到达,如果在题目中遇到这种情况,默认新到达的进程先进入就绪队列)。
4时刻(P1(3) → P3(1) → P2(2)):4时刻,P3到达,先插到就绪队尾,紧接着,P2下处理机也插到队尾。
5时刻(P3(1) → P2(2) → P4(6)):5时刻,P4到达插到就绪队尾(注意:由于P1的时间片还没用完,因此暂时不调度。另外,此时P1处于运行态,并不在就绪队列中)。
6时刻(P3(1) → P2(2) → P4(6) → P1(1)):6时刻,P1时间片用完,下处理机,重新放回就绪队尾,发生调度。
7时刻(P2(2) → P4(6) → P1(1)):虽然P3的时间片没用完,但是由于P3只需运行1个单位的时间,运行完了会主动放弃处理机,因此也会发生调度。队头进程P2上处理机。
9时刻(P4(6) → P1(1)):进程P2时间片用完,并刚好运行完,发生调度,P4上处理机。
11时刻(P1(1) → P4(4) ):P4时间片用完,重新回到就绪队列。P1上处理机。
12时刻(P4(4) ):P1运行完,主动放弃处理机,此时就绪队列中只剩P4,P4上处理机。
14时刻():就绪队列为空,因此让P4接着运行一个时间片。
16时刻:所有进程运行结束。
在这里插入图片描述
时间片大小为 5
0时刻(P1(5) ):只有P1到达,P1上处理机。
2时刻(P2(4)):P2到达,但P1时间片尚未结束,因此暂不调度
4时刻(P2(4) → P3(1)):P3到达,但P1时间片尚未结束,因此暂不调度
5时刻(P2(4) → P3(1) → P4(6) ):P4到达,同时,P1运行结束。发生调度,P2上处理机。
9时刻(P3(1) → P4(6) ):P2运行结束,虽然时间片没用完,但是会主动放弃处理机。发生调度。
10时刻( P4(6) ):P3运行结束,虽然时间片没用完,但是会主动放弃处理机。发生调度。
15时刻( ):P4时间片用完,但就绪队列为空,因此会让P4继续执行一个时间片。
16时刻( ):P4运行完,主动放弃处理机。所有进程运行完。
在这里插入图片描述
若按照先来先服务调度算法,则是这样:
在这里插入图片描述
如果时间片太大,使得每个进程都可以在一个时间片内就完成,则时间片轮转调度算法退化为先来先服务调度算法,并且会增大进程响应时间。因此时间片不能太大
另一方面,进程调度、切换是有时间代价的(保存、恢复运行环境),因此如果时间片太小,会导致进程切换过于频繁,系统会花大量的时间来处理进程切换,从而导致实际用于进程执行的时间比。(一般来说,设计时间片时要让切换进程的开销占比不超过1%)

6. 优先级调度算法

优先级调度算法又称优先权调度算法,它既可用于作业调度,又可用于进程调度。该算法中的优先级用于作业运行的紧迫程度

  1. 算法思想: 随着计算机的发展,特别是实时操作系统的出现,越来越多的应用场景需要根据任务的紧急程度来决定处理顺序。
  2. 算法规则: 每个作业/进程有各自的优先级,调度时选择优先级最高的作业/进程。
  3. 用于作业/进程调度: 既可用于作业调度,也可用于进程调度。甚至,还会用于在之后会学习的I/O调度中。
  4. 是否可抢占? 抢占式、非抢占式都有。做题时的区别在于:非抢占式只需在进程主动放弃处理机时进行调度即可,而抢占式还需在就绪队列变化时,检查是否会发生抢占。
  5. 优缺点: 优点:用优先级区分紧急程度、重要程度,适用于实时操作系统。可灵活地调整对各种作业/进程的偏好程度。缺点:若源源不断地有高优先级进程到来,则可能导致饥饿。
  6. 是否会导致饥饿:
  7. 补充: 就绪队列未必只有一个,可以按照不同优先级来组织。另外,也可以把优先级高的进程排在更靠近队头的位置。
    根据优先级是否可以动态改变,可将优先级分为静态优先级动态优先级两种。
    静态优先级:创建进程时确定,之后一直不变。
    动态优先级:创建进程时有一个初始值,之后会根据情况动态地调整优先级。

例题:各进程到达就绪队列的时间、需要的运行时间、进程优先数如下表所示。使用非抢占式优先级调度算法,分析进程运行情况。(注:优先数越大,优先级越高)(这个是不同的题目不一样的,有的题目是“优先数越小,优先级越大”,要根据不同的题目要求来做题)
在这里插入图片描述
注:以下括号内表示当前处于就绪队列的进程
0时刻(P1):只有P1到达,P1上处理机。
7时刻(P2、P3、P4):P1运行完成主动放弃处理机,其余进程都已到达,P3优先级最高,P3上处理机。
8时刻( P2、P4 ):P3完成,P2、P4优先级相同,由于P2先到达,因此P2优先上处理机。
12时刻( P4):P2完成,就绪队列只剩P4,P4上处理机。
16时刻( ):P4完成,所有进程都结束。

例题:各进程到达就绪队列的时间、需要的运行时间、进程优先数如下表所示。使用抢占式的优先级调度算法,分析进程运行情况。(注:优先数越大,优先级越高)
在这里插入图片描述
注:以下括号内表示当前处于就绪队列的进程
0时刻(P1):只有P1到达,P1上处理机。
2时刻(P2):P2到达就绪队列,优先级比P1更高,发生抢占。P1回到就绪队列,P2上处理机。
4时刻(P1、P3):P3到达,优先级比P2更高,P2回到就绪队列,P3抢占处理机。
5时刻(P1、P2、P4):P3完成,主动释放处理机,同时,P4也到达,由于P2比P4更先进入就绪队列,
因此选择P2上处理机
7时刻(P1、P4):P2完成,就绪队列只剩P1、P4,P4上处理机。
11时刻(P1 ):P4完成,P1上处理机
16时刻():P1完成,所有进程均完成

  • 如何合理地设置各类进程的优先级?
    通常: 系统进程优先级高于用户进程
    前台进程优先级高于后台进程
    操作系统更偏好 I/O型进程(或称 I/O繁忙型进程)( I/O设备和CPU可以并行工作。如果优先让I/O繁忙型进程优先运行的话, 则越有可能让I/O设备尽早地投入工作,则资源利用率、系统吞吐量都会得到提升)
    注:与I/O型进程相对的是计算型进程(或称 CPU繁忙型进程)
  • 如果采用的是动态优先级,什么时候应该调整?
    可以从追求公平、提升资源利用率等角度考虑
    如果某进程在就绪队列中等待了很长时间,则可以适当提升其优先级
    如果某进程占用处理机运行了很长时间,则可适当降低其优先级
    如果发现一个进程频繁地进行I/O操作,则可适当提升其优先级
7. 多级反馈队列调度算法
  1. 算法思想: 对其他调度算法的折中权衡
  2. 算法规则: ①设置多级就绪队列,各级队列优先级从高到低,时间片从小到大。
    ②新进程到达时先进入第1级队列,按FCFS原则排队等待被分配时间片,若用完时间片进程还未结束,则进程进入下一级队列队尾。如果此时已经是在最下级的队列,则重新放回该队列队尾。
    ③只有第 k 级队列为空时,才会为 k+1 级队头的进程分配时间片。
  3. 用于作业/进程调度: 用于进程调度
  4. 是否可抢占? 抢占式的算法。在 k 级队列的进程运行过程中,若更上级的队列(1~k-1级)中进入了一个新进程,则由于新进程处于优先级更高的队中,因此新进程会抢占处理机,原来运行的进程放回 k 级队列队尾。
  5. 优缺点: 对各类型进程相对公平(FCFS的优点);每个新到达的进程都可以很快就得到响应(RR的优点);短进程只用较少的时间就可完成(SPF的优点);不必实现估计进程的运行时间(避免用户估计出错); 可灵活地调整对各类进程的偏好程度,比如CPU密集型进程、I/O密集型进程(拓展:可以将因I/O而阻塞的进程重新放回原队列,这样I/O型进程就可以保持较高优先级)
  6. 是否会导致饥饿:

在这里插入图片描述
设置多级就绪队列,各级队列优先级高到低时间片从小到大
新进程到达时先进入第1级队列,按FCFS原则排队等待被分配时间片。若用完时间片进程还未结束,则进程进入下一级队列队尾。如果此时已经在最下级的队列,则重新放回最下级队列队尾。
只有第 k 级队列为空时,才会为== k+1 级队头的进程==分配时间片;被抢占处理机的进程重新放回原队列队尾

2.3.6 补充

  1. 先来先服务调度算法有利于CPU繁忙型的作业,而不利于I/O繁忙型的作业。FCFS调度算法比较有利于长作业,而不利于短作业。所谓CPU繁忙型的作业,是指该类作业需要大量的CPU时间进行计算,而很少请求I/O操作。I/O繁忙型的作业是指CPU处理时,需要频繁地请求I/O操作。所以CPU繁忙型作业更接近于长作业。
  2. 在同一台处理器上以单道方式运行时,多道作业同时到达的情况下,要想获得最短的平均周转时间,用短作业优先调度算法会有较好的效果。
  3. 作业是从用户角度出发的,它由用户提交,以用户任务为单位;进程是从操作系统出发的,由系统生成,是操作系统的资源分配和独立运行的基本单位。
  4. 中断向量本身是用于存放中断服务例行程序的入口地址,而中断向量地址就应是该入口地址的地址。
  5. 短任务优先调度不管是抢占式的还是非抢占的,当系统总是出现新来的短任务时,长任务会总是得不到处理机,产生饥饿现象。
  6. 多级反馈队列调度算法能较好地满足各种类型用户的需要。对于终端型作业用户而言,由于它们提交的作业大多属于交互型作业,作业通常比较短小,系统只要能使这些作业在第一级队列所规定的时间片内完成,便可使终端型作业用户感到满意;对于短批处理作业用户而言,它们的作业开始时像终端型作业一样,若仅在第一级队列中执行一个时间片即可完成,便可获得与终端型作业一样的响应时间;对于稍长的作业,通常也只需要在第2级队列和第3级队列中各执行一个时间片即可完成,其周转时间仍然较短;对于长批处理作业用户而言,它们的长作业将依次在第1,2,……,n级队列中运行,然后按时间片轮转方式运行,用户不必担心其作业长期得不到处理。

其他章节:
操作系统王道考研复习——第一章(计算机系统概述)
操作系统王道考研复习——第二章(进程管理) 下
操作系统王道考研复习——第三章(内存管理/存储器管理)
操作系统王道考研复习——第四章(文件管理)
操作系统王道考研复习——第五章(设备管理)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值