【王道操作系统】第二章 进程与线程

第二章 进程与线程

  • 一、进程与线程
    • 1. 进程的概念
    • 2. 进程的组成
      • ●PCB
      • ●程序段
      • ●数据段
    • 3. 进程的特征
    • 4.进程的组织
      • 进程的组织方式
    • 5. 进程的状态与转换
      • 进程的状态
      • 状态间的转换
      • 进程的组织方式(各个进程PCB的组织方式)
    • 6. 进程控制
      • 基本概念
      • 相关的原语
        • (1)进程的创建
        • (2)进程的终止
        • (3)进程的阻塞和唤醒
          • 进程的阻塞
          • 进程的唤醒
        • (4)进程的切换
    • 7. 进程通信
      • 共享存储
      • 管道通信
      • 消息传递
    • 8. 线程的概念和多线程模型
      • 线程的概念
      • 线程的实现方式
      • 多线程模型
  • 二、处理机调度
    • 1. 调度的概念、层次
      • 调度的基本概念
      • 调度的三个层次
      • 【补充知识】进程的挂起态与七状态模型
    • 2. 调度的时机、切换与过程、方式
      • 进程调度的时机
      • 进程调度的方式
      • 进程的切换与过程
    • 3. 调度算法的评价指标
      • CPU利用率
      • 系统吞吐量
      • 周转时间
      • 等待时间
      • 响应时间
    • 4. 调度算法:FCFS、SJF、HRRN
      • FCFS 先来先服务
      • SJF 短作业优先
      • HRRN 高响应比优先
    • 5. 调度算法:时间片轮转、优先级、多级反馈队列
      • 时间片轮转(RR)
      • 优先级
      • 多级反馈队列
  • 三、进程同步
    • 1. 进程同步、进程互斥
      • 什么是 进程同步
      • 什么是 进程互斥
    • 2. 实现临界区互斥的基本方法
      • 进程互斥的软件实现方法
        • ● 单标志法
        • ● 双标志先检查
        • ● 双标志后检查
        • ● Peterson算法
      • 进程互斥的硬件实现方法
        • ● 中断屏蔽方法
        • ● TestAndSet(TS指令/TSL指令)
        • ● Swap指令(XCHG指令)
    • 3. 信号量
      • 信号量机制
        • ● 整型信号量
        • ● 记录型信号量
      • 用信号量实现进程互斥
      • 用信号量实现进程同步
    • 4. 经典同步问题
      • ● 生产者-消费者问题
      • ● 多生产者-多消费者问题
      • ● 吸烟者问题
      • ● 读者写者问题
      • ● 哲学家进餐问题
    • 5. 管程
      • ● 拓展1:用管程解决生产者消费者问题
      • ● 拓展2:Java中类似管程的机制
  • 四、死锁
    • 1. 死锁的概念
    • 2. 预防死锁(静态策略)
    • 3. 避免死锁(动态策略)
      • 什么是安全序列
      • 银行家算法
    • 4. 死锁检测和解除
      • 死锁的检测
      • 死锁的解除

一、进程与线程

1. 进程的概念

  • 程序:是 静态的,就是个存放在磁盘里的可执行文件,就是一系列的指令集合。
  • 进程(Process):是 动态的,是程序的一次执行过程。
    • 同一个程序多次执行会对应多个进程

2. 进程的组成

  • PCB 是给 操作系统用的程序段、数据段给进程自己用的

  • 一个 进程实体(进程映像)PCB、程序段、数据段 组成

  • 进程动态 的,进程实体(进程映像)静态 的。

  • 进程 是进程实体的 运行过程,是系统进行 资源分配调度 的一个独立单位

    一个进程被“调度”,就是指操作系统决定让这个进程上CPU运行

●PCB

  • 当进程被创建时,操作系统会为其分配一个 唯一的、不重复 的“身份证”——PID(Process ID、进程ID)

  • 进程控制块(PCB):

    PCB是进程存在的唯一标志,当进程被创建时,操作系统为其创建PCB,当进程结束时,会回收其PCB

    • 进程描述信息
      • 进程标识符PID
      • 用户标识符UID
    • 进程控制和管理信息
      • CPU、磁盘、网络流量使用情况统计…
      • 进程当前状态:就绪态/阻塞态/运行态…
    • 资源分配清单
      • 正在使用哪些文件
      • 正在使用哪些内存区域
      • 正在使用哪些I/O设备
    • 处理机相关信息
      • eg. PSW、PC等等各种寄存器的值(用于实现进程切换)
  • 这些信息被保存在一个数据结构 PCB 中(Process Control Block)中,即 进程控制块

  • 操作系统需要对各个并发运行的进程进行管理,但凡管理时所需要的信息,都会被放在PCB中

●程序段

  • 程序的代码(指令序列)

●数据段

  • 运行过程中产生的各种数据(eg.程序中定义的变量)

3. 进程的特征

  • 动态性:进程是程序的一次执行过程,是动态地产生、变化和消亡的

    动态性是进程最基本的特征

  • 并发性:内存中有多个进程实体,各进程可并发执行

  • 独立性:进程是能独立进行、独立获得资源、独立接受调度基本单位

  • 异步性:各进程按各自独立的、不可预知的速度向前推进,操作系统要提供“进程同步机制”来解决异步问题

    异步性会导致并发程序执行结果的不确定性。

  • 结构性:每个进程都会配置一个PCB。结构上看,进程由程序段、数据段、PCB组成

4.进程的组织

  • 进程的 组成 讨论的是 一个进程内部 由哪些部分构成的问题

  • 进程的 组织 讨论的是 多个进程之间 的组织方式问题

进程的组织方式

  • 链接方式

    • 按照进程状态将PCB分为多个队列
    • 操作系统持有指向各个队列的指针
  • 索引方式

    • 根据进程状态的不同,建立几张索引表
    • 操作系统持有指向各个索引表的指针

5. 进程的状态与转换

进程的状态

就绪态、运行态、阻塞态是进程的三种基本状态

进程PCB中会有一个变量state来表示进程的当前状态

  • 创建态(New,又称新建态)

    进程正在被创建,在这个阶段系统会分配资源、初始化PCB

  • 就绪态 (Ready)

    进程创建完成后进入“就绪态”,此时进程具备运行条件,但由于没有空闲的CPU,暂不能运行

    • 注:进程已有除处理机纸外所需的资源,一旦获得处理机即可进入运行态开始运行。(万事俱备,只欠CPU
  • 运行态 (Running)

    占有CPU,并在CPU上运行

    • 注:单核处理机:每一时刻最多只有一个进程处于运行态

      双核处理机:每一时刻最多可以同时有两个进程处于运行态

  • 阻塞态 (Waiting/Blocked,又称等待态)

    因等待某一事件而暂时不能运行

    • 注:如操作系统分配打印机、等待读磁盘操作的结果。

    • 为提高CPU利用率,需先将其他进程所需资源分配到位,才能得到CPU的服务。

    • 就绪态:有资源、欠CPU

      阻塞态:欠资源、欠CPU

  • 终止态(Terminated,又称结束态)

    进程正在从系统中撤销,操作系统会回收进程拥有的资源、撤销PCB

状态间的转换

【王道操作系统】第二章 进程与线程_第1张图片

  • 就绪态——>运行态

    进程被调度

  • 运行态——>就绪态

    时间片到,或CPU被其他高优先级的进程抢占

  • 运行态——>阻塞态

    等待系统资源分配,或等待某事件发生(主动行为)

  • 阻塞态——>就绪态

    资源分配到位,等待的事件发生(被动行为)

  • 创建态——>就绪态

    系统完成创建进程的相关操作

  • 运行态——>终止态

    进程运行结束,或运行过程中遇到不可修复的错误

进程的组织方式(各个进程PCB的组织方式)

6. 进程控制

基本概念

  • 概念:进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能

  • 如何实现进程控制——原语(运行在 核心态)

    • 原语的特点是执行期间 不允许中断 ,只能一气呵成。

    • 这种不可被中断的操作即 原子操作

    • 原语采用 “关中断 指令”和 “ 开中断 指令”实现

      • 关/开中断指令 的权限非常大,是只允许在 核心态 下执行的 特权指令
    • 原语做的三类事:

      • 更新PCB中信息

        eg:

        1. 修改进程状态标志、将运行环境保存到PCB、从PCB恢复运行环境
        2. 剥夺当前运行进程的CPU的使用权必然需要保存其运行环境
        3. 某进程开始运行前必然要恢复其运行环境
      • 将PCB插入合适的队列

      • 分配/回收资源

相关的原语

(1)进程的创建
  • 创建原语(无——>创建态——>就绪态)
    • 申请空白PCB
    • 为新进程分配所需资源
    • 初始化PCB
    • 将PCB插入就绪队列(创建态——>就绪态)
  • 引起进程创建的事件
    • 用户登录
      • 分时系统中,用户登录成功,系统会为其建立一个新的进程
    • 作业调度
      • 多道批处理系统中,有新的作业放入内存时,会为其创建一个新的进程
    • 提供服务
      • 用户向操作系统提出某些请求,会新建一个进程处理该请求
    • 应用请求
      • 由用户进程主动请求创建一个子进程
(2)进程的终止
  • 撤销原语(就绪态/阻塞态/运行态——>终止态——>无)
    • 从PCB集合中找到终止进程的PCB
    • 若进程正在运行,立即剥夺CPU,将CPU分配给其他进程
    • 终止其所有子进程(进程间的关系是树形结构)
    • 将该进程拥有的所有资源归还给父进程或操作系统
    • 删除PCB
  • 引起进程终止的事件
    • 正常结束:进程请求终止(exit系统调用)
    • 异常结束:整数除以0、非法使用特权指令、如何被操作系统强行杀掉
    • 外界干预:Ctrl+Alt+delete,用户选择杀掉进程
(3)进程的阻塞和唤醒

阻塞原语和唤醒原语必须成对使用

进程的阻塞
  • 阻塞原语(运行态——>阻塞态)
    • 找到要阻塞的进程对应的PCB
    • 保护进程运行现场,将PCB状态信息设置为“阻塞态”,暂时停止进程运行
    • 将PCB插入相应事件的等待队列
  • 引起进程阻塞的事件
    • 需要等待系统分配某种资源
    • 需要等待相互合作的进程完成工作
进程的唤醒
  • 唤醒原语(阻塞态——>就绪态)
    • 在事件等待队列中找到PCB
    • 将PCB从等待队列移除,设置进程为就绪态
    • 将PCB插入就绪队列,等待被调度
  • 引起进程唤醒的事件
    • 等待的事件发生(因何事阻塞,就应由何事唤醒
(4)进程的切换
  • 切换原语(运行态——>阻塞态/就绪态,就绪态——>运行态)
    • 运行环境信息 存入PCB(进程上下文Context)
    • PCB移入相应队列
    • 选择另一个进程执行,并更新其PCB
    • 根据PCB恢复 新进程所需的运行环境
  • 引起进程切换的事件
    • 当前进程时间片到
    • 由更高优先级的进程到达
    • 当前进程主动阻塞
    • 当前进程终止

7. 进程通信

  • 概念:进程通信是指进程之间的信息交换
  • 进程是分配系统资源的单位(包括内存地址空间),因此 各进程 拥有的 内存地址空间相互独立
为了保证安全, 一个进程不能直接访问另一个进程的地址空间
但进程间的信息交换又是必须实现的。
为保证进程间的安全通信,操作系统提供了一些方法。

 

共享存储

  • 基于数据结构 的共享:

    比如共享空间里只能放一个长度为10的数组。

    这种共享方式速度慢、限制多,是一种 低级通信 方式。

  • 基于存储区 的共享:

    在内存中画出一块共享存储区,数据的形式、存放位置都由进程控制,而不是操作系统。

    相比之下,这种共享方式速度更快,是一种 高级通信 方式。

 

管道通信

  1. 管道只能采用 半双工通信 ,某一时间段内只能实现 单向的传输

    如果要实现 双向同时通信,则 需要设置两个管道

  2. 各进程要 互斥 地访问管道。

  3. 数据以 字符流 的形式写入管道,当 管道写满 时,写进程 的write() 系统调用将被 阻塞,等待读进程将数据取走。

    当读进程将数据全部取走后,管道变空,此时 读进程 的read() 系统调用将被 阻塞

  4. 如果 没写满,就不允许读

    如果 没读空,就不允许写

  5. 数据一旦被读出,就从管道中被抛弃,这意味着 读进程最多只能有一个,否则可能会有读错数据的情况。

 

消息传递

  • 进程间的数据交换以 格式化的消息(Message)为单位。

    进程通过操作系统提供的 “发送消息/接收消息” 两个 原语 进行数据交换。

  • 直接通信方式

    消息直接挂到接收进程的 消息缓冲队列

     

  • 间接通信方式

    消息要先发送到中间实体(信箱)中,因此也称 “信箱通信方式”。

    eg:计网中的电子邮件系统。

 

8. 线程的概念和多线程模型

线程的概念

 

 

  • 可以把线程理解为 “轻量级进程”.
  • 线程 是一个 基本的CPU执行单元,也是 程序执行流的最小单位
  • 引入线程后,不仅是进程之间可以并发,进程内的 各线程之间 也可以 并发,从而进一步 提升了系统的并发度,使得一个进程内也可以并发处理各种任务(如QQ视频、文字聊天、传文件)
  • 引入线程后,进程 只作为 除CPU之外的系统资源的分配单元(如打印机、内存地址空间等都是分配给进程的)。
  • 引入线程机制后的变化:

  • 线程的属性:

 

线程的实现方式

  • 用户级线程(User-Level Thread,ULT)

    • 历史背景:

    • 例:

       

    • 很多编程语言提供看强大的线程库,可以实现线程的创建、销毁、调度等功能。

    1、用户级线程由 应用程序 通过线程库实现,所有的 线程管理工作 都由 应用程序负责(包括线程切换)。

    2、用户级线程中,线程切换 可以在 用户态下即可完成,无需操作系统干预。

    3、在用户看来,是有多个线程。但是在操作系统内核看来,并意识不到线程的存在。用户级线程 就是 “从用户视角看能看到的线程”

    4、优缺点:

    优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高。

    缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。

 

  • 内核级线程(Kernel-Level Thread,KLT,又称“内核支持的线程”)

    由操作系统支持的线程

    1、内核级线程的管理工作操作系统内核 完成。

    2、线程调度、切换等工作都由内核负责,因此 内核级线程的切换 必然需要在 核心态 下才能完成。

    3、操作系统会为每个内核级线程建立相应的TCB(Thread Control Block,线程控制块),通过TCB对线程进行管理。“内核级线程” 就是 从操作系统内核视角看能看到的线程

    4、优缺点:

    优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。

    缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。

 

多线程模型

  • 一对一 模型 :一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。

    (优缺点见内核级线程的优缺点)

  • 多对一 模型:多个用户级线程映射到一个内核级线程。且一个进程只被分配一个内核级线程。

    (优缺点见用户级线程的优缺点)

    • 操作系统只 “看得见” 内核级线程,因此只有 内核级线程才是处理机分配的单位
  • 多对多 模型:n用户级线程映射到m内核级线程( n ≥ m )。每个用户进程对应m个内核级线程。、

    克服了多对一模型并发度不高的缺点(一个阻塞全体阻塞);

    克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。

 

二、处理机调度

1. 调度的概念、层次

调度的基本概念

 

调度的三个层次

  • 高级调度

    高级调度(作业调度)

    按一定的原则从外存的作业后备队列中挑选一个作业调入内存,并创建进程。每个作业只调入一次,调出一次。作业调入时会建立PCB,调出时才撤销PCB。

  • 低级调度

    低级调度(进程调度/处理机调度)

    按照某种策略从就绪队列中选取一个进程,将处理机分配给它。

    进程调度是操作系统中 最基本的一种调度,在一般的操作系统中都必须配置进程调度。

    进程调度的 频率很高,一般几十毫秒一次。

  • 中级调度

    中级调度(内存调度)

    按照某种策略决定将哪个处于挂起状态的进程重新调入内存。

    一个进程可能会被多次调出、调入内存,因此 中级调度 发生的 频率 要比高级调度 更高

 

  • 三层调度的联系、对比

 

【补充知识】进程的挂起态与七状态模型

 

 

2. 调度的时机、切换与过程、方式

进程调度的时机

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

    一个时间段内只允许一个进程使用的资源。各进程需要 互斥地 访问临界资源;

    临界区:

    访问临界资源的那段代码。

    • 进程在 操作系统内核程序临界区不能 进行调度和切换 √

      会先上锁

    • 进程处于 临界区不能 进行处理机调度 ×

进程调度的方式

  1. 非剥夺方式

    又称 非抢占方式。即,只允许进程主动放弃处理机。在运行过程中即便有更紧迫的任务到达,当前进程依然会继续使用处理机,直到该进程终止或主动要求进入阻塞态。

    实现简单,系统开销小但无法及时处理紧急任务,适合于早期的批处理系统。

  2. 剥夺调度方式

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

    可以优先处理更紧急的进程,也可实现让各进程按时间片轮流执行的功能(通过时钟中断)。适合于分时操作系统、实时操作系统。

进程的切换与过程

  • "狭义的进程调度"与“进程切换”的区别:

    image-20220331120404674

  • 进程切换的过程主要完成了:

    1、对原来运行进程各种数据的保存;

    2、对新的进程各种数据的恢复;

    (如:程序计数器、程序状态字、各种数据寄存器等处理机现场信息,这些信息一般保存在进程控制块)

注意:

进程切换是有代价的,因此如果 过于频繁的 进行进程 调度、切换,必然会使整个 系统效率降低,使系统大部分时间都花在了进程切换上,而真正用于执行进程的时间减少

本小节不是考试重点,但需要理解。

3. 调度算法的评价指标

CPU利用率

CPU造价昂贵,希望让CPU尽可能多地工作

  • CPU利用率

    指 CPU “忙碌” 的时间占总时间的比例。

  • 利用率
    利 用 率 = 忙 碌 的 时 间 总 时 间 利用率=\frac{忙碌的时间}{总时间} =

eg:

系统吞吐量

对于计算机来说,希望能用尽可能少的时间处理完尽可能多的作业

  • 系统吞吐量

    单位时间内完成作业的数量

    系 统 吞 吐 量 = 总 共 完 成 了 多 少 道 作 业 总 共 花 了 多 少 时 间 系统吞吐量=\frac{总共完成了多少道作业}{总共花了多少时间} =

eg:

周转时间

对于计算机来说,他很关心自己的作业从提交到完成花了多少时间

  • 周转时间

    是指 作业被提交给系统开始,到 作业完成为止 的这段时间间隔

    它包括四个部分:

    1、作业在外存后备队列上等待作业调度(高级调度)的时间

    2、进程在就绪队列上等待进程调度(低级调度)的时间

    3、进程在CPU上执行的时间

    4、进程等待 I/O 操作完成的时间

    后三项在一个作业的整个处理过程中,可能发生多次

    • (作业)周转时间
      ( 作 业 ) 周 转 时 间 = 作 业 完 成 时 间 − 作 业 提 交 时 间 (作业)周转时间=作业完成时间-作业提交时间 =
      对于用户来说,跟关心自己的单个作业的周转时间

    • 平均周转时间
      平 均 周 转 时 间 = 各 作 业 周 转 时 间 之 和 作 业 数 平均周转时间=\frac{各作业周转时间之和}{作业数} =

    对于操作系统来说,更关心系统的整体表现,因此更关心所有作业周转时间的平均值

    • 带权周转时间

    带 权 周 转 时 间 = 作 业 周 转 时 间 作 业 实 际 运 行 的 时 间 = 作 业 完 成 时 间 − 作 业 提 交 时 间 作 业 实 际 运 行 的 时 间 带权周转时间=\frac{作业周转时间}{作业实际运行的时间}=\frac{作业完成时间-作业提交时间}{作业实际运行的时间} ==

    带权周转时间必然≥1

    带权周转时间与周转时间都是越小越好

    • 平均带权周转时间

    平 均 带 权 周 转 时 间 = 各 作 业 带 权 周 转 时 间 之 和 作 业 数 平均带权周转时间=\frac{各作业带权周转时间之和}{作业数} =

等待时间

计算机的用户希望自己的作业尽可能少的等待处理机

  • 等待时间

    指进程/作业 处于等待处理机状态时间之和,等待时间越长,用户满意度越低。

    对于 进程 来说,等待时间就是指进程建立后 等待被服务的时间之和,在等待I/O完成的期间其实进程也是在被服务的,所以不计入等待时间。

    对于 作业 来说,不仅要考虑 建立进程后的等待时间,还要加上作业在外村后备队列中等待的时间

一个作业总共需要被CPU服务多久,被I/O设备服务多久一般是确定不变的,因此调度算法其实只会影响作业/进程的等待时间。

与前面指标类似,也有“平均等待时间”来评价整体性能。

响应时间

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

  • 响应时间

    指从用户 提交请求首次产生响应 所用的时间

4. 调度算法:FCFS、SJF、HRRN

FCFS 先来先服务

FCFS——First Come First Serve

  • 算法思想:主要从“公平”角度考虑

  • 算法规则:按照作业/进程到达的先后顺序进行服务

  • 用于作业/进程调度:

    用于作业调度时,考虑的是哪个作业先到达后备队列;

    用于进程调度时,考虑的是哪个进程先到达就绪队列;

  • 是否可抢占: 非抢占式的算法

  • 优缺点:

    优点:公平、算法实现简单

    缺点:排在长作业(进程)后面的短作业需要等待很长时间,带权周转时间很大,对短作业来说用户体验不好。即,FCDS算法 对长作业有利,对短作业不利

  • 是否会导致 饥饿:不会 (只要等就会轮到)

补充:饥饿:指某进程/作业长期得不到服务

例:

注意到P3的带权周转时间很大,这意味着P3本来需要很少的时间运行,却等待了很长时间。

 

SJF 短作业优先

SJF——Shortest Job First

  • 算法思想:追求最少的平均等待时间,最少的平均周转时间、最少的平均平均带权周转时间

  • 算法规则:最短的作业/进程优先得到服务(所谓“最短”,指要求服务时间最短)

  • 用于作业/进程调度:

    即可用于作业调度,也可用于进程调度。

    用于进程调度时称为 “短进程优先(SPF,Shortest Process First)算法”;

  • 是否可抢占: SJF和SPF是 非抢占式的 算法,但是 也有抢占式的版本—— 最短剩余时间优先 算法(SRTN,Shortest Remaining Time Next)

  • 优缺点:

    优点:“最短的” 平均等待时间、平均周转时间

    缺点:不公平。 对短作业有利,对长作业不利。可能产生 饥饿现象。另外,作业/进程的运行时间是由用户提供的,并不一定真实,不一定能做到真正的短作业优先。

  • 是否会导致 饥饿:会

    如果源源不断的有短作业/进程到来,可能使长作业/进程长时间得不到服务,产生 “ 饥饿 ”现象。如果一直得不到服务,则称为 “ 饿死

例:

非抢占式:

抢占式:


注意点:

 

HRRN 高响应比优先

HRRN——Highest Response Ratio Next

  • 算法思想:要综合考虑作业/进程的等待时间和要求服务的时间

  • 算法规则:在每次调度时先计算各个作业/进程的 响应比,选择 响应比最高的 作业/进程为其服务.
    响 应 比 = 等 待 时 间 + 要 求 服 务 时 间 要 求 服 务 时 间 响应比 = \frac{等待时间+要求服务时间}{要求服务时间} =+
    响应比 ≥ 1

  • 用于作业/进程调度:即可用于作业调度,也可用于进程调度。

  • 是否可抢占: 非抢占式的 算法,因此只有当前运行的作业/进程主动放弃处理机时,才需要调度,才需要计算响应比

  • 优缺点:

    优点:综合考虑了等待时间和运行时间(要求服务时间)

    等待时间相同时,要求服务时间短的优先(SJF的优点)

    要求服务时间相同时,等待时间长的优先(FCFS的优点)

    对于长作业来说,随着等待时间越来越久,其响应比也会越来越大,从而避免了长作业饥饿的问题

  • 是否会导致 饥饿:不会

例:

 

要动手算,算法特性容易考小题,算法的使用常结合调度算法的评价指标在大题中考察

 

5. 调度算法:时间片轮转、优先级、多级反馈队列

时间片轮转(RR)

RR——Round-Robin

  • 算法思想:公平地、轮流地为各个进程服务,让每个进程在一定时间间隔内都可以得到响应

  • 算法规则:按照各进程到达就绪队列的顺序,轮流让各个进程执行一个 时间片 (如100ms)。若进程未在一个时间片内执行完,则剥夺处理机,将进程重新放到就绪队列队尾重新排队

  • 用于作业/进程调度:用于进程调度(只要作业放入内存建立了相应的进程后,才能被分配处理机时间片)

  • 是否可抢占: 若进程未能在时间片内运行完,将被强行剥夺处理机使用权,因此时间片轮转调度算法属于 抢占式 的算法。由 时钟装置 发出 时钟中断 来通知 CPU 时间片已到

  • 优缺点:

    优点:公平,响应快,适用于 分时操作系统

    缺点:由于高频率的进程切换,因此有一定开销;不区分任务的紧急程度

  • 是否会导致 饥饿:不会

例:

时间片大小为2时:




时间片大小为5时:

和先来先服务调度算法对比:

可以看到当时间片大小为5时和先来先服务算法是一致的

  • 补充:时间片太大或太小会有什么影响?(选择题中常考察)

1)如果 时间片太大,使得每个进程都可以在一个时间片内就完成,则时间片轮转调度算法 退化为先来先服务 调度算法,并且会 增大响应时间。因此 时间片不能太大

2)进程调度、切换是有时间代价的(保存、恢复运行环境),因此如果 时间片太小,会导致 进程切换过于频繁,系统会花大量的时间来处理进程切换,从而导致实际用于进程执行的时间比例减少。可见, 时间片也不能太小

 

优先级

  • 算法思想:随着计算机的发展,特别是实时操作系统的出现,越来越多的应用场景需要根据任务的紧急程度来决定处理顺序

  • 算法规则:调度时选择优先级最高的作业/进程

  • 用于作业/进程调度:即可用于作业调度,也可用于进程调度。甚至,还会用于之后学习的 I/O 调度中

  • 是否可抢占: 抢占式、非抢占式都有

    非抢占式:只需在进程主动放弃处理机时进行调度即可

    抢占式:需要在就绪队列变化时,检查是否会发生抢占

  • 优缺点:

    优点:用优先级区分紧急程度、重要程度,适用于 实时操作系统。可灵活地调整对各种作业/进程的偏好程度

    缺点:若源源不断地有高优先级进程到来,则可能导致饥饿

  • 是否会导致 饥饿:会

例:

(优先级和优先数不是一个意思,注意题意进行区分,有的题可能优先数越小优先级越高)

非抢占式:

抢占式:

  • 补充:

 

多级反馈队列

  • 算法思想:对其他调度算法的折中权衡

  • 算法规则:

    1)设置多级就绪队列,各级队列优先级从高到低,时间片从小到大

    2)新进程到达时先进入第1级队列,按FCFS原则排队等待被分配时间片,若用完时间片进程还未结束,则进程进入下一级队列队尾。如果此时已经是在最下级的队列,则重新放回该队列队尾

    3)只有第 k 级队列为空时,才会为 k + 1 级对头的进程分配时间片

  • 用于作业/进程调度:用于进程调度。

  • 是否可抢占: 抢占式 的算法。

    在k级队列的进程运行过程中,若更上级的队列(1~k-1级)中进入了一个新进程,则由于新进程处于优先级更高的队列中,因此新进程会抢占处理机,原来运行的进程放回k级队列队尾

  • 优缺点:

    优点:

    对各类型进程相对公平(FCFS的优点);

    每个新到达的进程都可以很快就得到响应(RR的优点);

    短进程只用较少的时间就可完成(SPF的优点);

    不必实现估计进程的运行时间(避免用户作假);

    可灵活地调整对各类进程的偏好程度,比如CPU密集型进程、I/O密集型进程(拓展:可将因I/O而阻塞的进程重新放回原对了,这样I/O型进程就可以保持较高优先级)

    缺点:可能导致饥饿

  • 是否会导致 饥饿:会

例:

 

三、进程同步

1. 进程同步、进程互斥

什么是 进程同步

回顾:进程具有 异步性 的特征。异步性是指,各并发执行的进程以各自独立的、不可预知的速度向前推进。

操作系统提供 ” 进程同步 机制 “ 来实现 ” 预知 “ 需求

如:

另一个例子:

同步 亦称 直接制约关系,它是指完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上 协调 它们的 工作次序 而产生的制约关系。进程间的直接制约关系就是源于它们之间的相互合作。

什么是 进程互斥

同时共享方式中,“同时”指宏观上看
  • 临界资源

    我们把 一个时间段内只允许一个进程使用 的资源称为 临界资源

    许多设备(如:摄像头、打印机)都属于临界资源,此外还有许多变量、数据、内存缓冲区等都属于临界资源。

    对临界资源的访问,必须 互斥 地进行。互斥,亦称 间接制约关系进程互斥 指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待。当访问临界资源的进程访问结束,释放该资源后,另一个进程才能去访问临界资源。

  • 对临界资源的互斥访问,可在逻辑上分为如下四部分:

    临界区 是进程中 访问临界资源 的代码段
    进入区退出区负责实现互斥 的代码段
    临界区也可称为“临界段”
  • 为实现对临界资源的互斥访问,同时保证系统整体性能,需遵循:

    1)空闲让进。临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区;

    2)忙则等待。当已有进程进入临界区时,其他试图进图临界区的进程必须等待;

    3)有限等待。对请求访问的进程,应保证能在有限时间内进入临界区(保证不会饥饿);

    4)让权等待。当进程不能进入临界区时,应立即释放处理机,防止进程忙等待。

2. 实现临界区互斥的基本方法

进程互斥的软件实现方法

如果不互斥访问:

如何实现进程互斥:

● 单标志法

● 双标志先检查

若两进程并发运行,会产生问题:

● 双标志后检查

可能会产生都在等待的情况:

● Peterson算法

Peterson 算法用软件方法解决了进程互斥问题,遵循了空闲让进、忙则等待、有限等待三个原则,但是依然 未遵循让权等待 的原则。

(因为进程进不了临界区,一直被卡在while循环中,一直还在CPU上执行,不断检查while循环的条件,会占用CPU资源,未满足让权等待原则)


Peterson 算法较前三种方案来说是最好的,但还不够好。

 

抓住 “谦让” 和 “表达意愿”

进程互斥的硬件实现方法

● 中断屏蔽方法
● TestAndSet(TS指令/TSL指令)
● Swap指令(XCHG指令)

 

image-20220411185546018

3. 信号量

本小节常考

信号量机制

用户进程可以通过使用操作系统提供的 一对原语 来对 信号量 进行操作,从而很方便的实现了进程互斥、进程同步。

  • 信号量

    其实就是一个变量 可以是一个整数,也可以是更复杂的记录型变量

    可以用一个信号量来 表示系统中某种资源的数量,比如:系统中只有一台打印机,就可设置一个初值为1的信号量。

    注意 一个信号量对应一种资源

  • 原语

    是一种特殊的程序段,其 执行只能一气呵成,不可被中断。原语是由 关中断/开中断指令 实现的。

    软件解决方案的主要问题是由 “进入区的各种操作无法一气呵成”,因此如果能把进入区、退出区的操作都用 “原语” 实现,使这些操作能 “一气呵成” 就能避免问题。

  • 一对原语

    【王道操作系统】第二章 进程与线程_第2张图片

● 整型信号量
● 记录型信号量

如:



Tip:

单词联想记忆法:

(1)P对应单词pause,即暂停的意思,行动前先暂停检查下可用资源,等待(wait)到资源后即可行动;

(2)V对应单词,victory,行动胜利即凯旋卸甲(释放资源)

该记忆法源自网络

 

用信号量实现进程互斥

用信号量实现进程同步

进程同步:

实现进程同步:

更复杂的同步问题:

 

4. 经典同步问题

● 生产者-消费者问题

消费者进程从缓冲区取出数据,若生产者进程处于阻塞态,消费者进程需将其唤醒,使生产者进程处于就绪态(生产者进程不会立即往缓冲区填数据)。

如果进程同时访问临界区,可能会出现问题,如两个生产者进程,可能会向同一块区域写入数据,造成数据覆盖,所以要互斥地访问。



  • 思考:能否改变相邻P、V操作的顺序?

生产和使用产品能否放到PV之间:

逻辑上是可以的。但是会使临界区代码变得更长,也就是说一个进程对临界区上锁的时间会变得更长,不利于各个进程交替的使用临界区资源,因此临界区代码要尽可能短。所以实际上不建议放在PV之间。


重要考点:

实现互斥的P操作要在实现同步的P操作之后,否则会导致死锁问题。

 

● 多生产者-多消费者问题

  • 问题描述:

不同的生产者和消费者所生产和消费的东西是不一样的,多指 “多类”

  • 问题分析:

    1、关系分析:

    2、整理思路:根据各进程操作流程确定P、V操作顺序

    ​ 互斥:在临界区前后分别 PV;

    ​ 同步:前 V 后 P。

    3、设置信号量:

    ​ 互斥信号量初值一般为1;

    ​ 同步信号量初值要看对应资源的初始值是多少。

  • 实现:

    能否去掉互斥信号量?

    即使不设置专门的互斥变量 mutex,也不会出现多个进程同时访问盘子的现象。

    原因在于:此题缓冲区大小为1,在任何时刻,apple、orange、plate三个同步信号量中最多只有一个是1。因此在任何时刻,最多只有一个进程的P操作不会被阻塞,并顺利地进入临界区。

    若将盘子容量改为2,即缓冲区大小为2:

  • 重要考点:

    从 “事件” 角度考虑:

 

● 吸烟者问题

  • 问题描述:

    生产者生产多种产品

  • 问题分析:

    1、分析关系:

    2、整理思路

    3、设置信号量

  • 实现:

    是否需要设置一个专门的互斥信号量?

    不需要。缓冲区大小为1,同一时刻,四个同步信号量中至多有一个的值为1.

  • 重要考点:

 

● 读者写者问题

  • 问题描述:

    读者——读,写者——写

  • 问题分析:

  • 实现:

    count 解决读者和读者之间可能不能同时访问的问题:

    但是起初的 “加锁” 操作可能仍然会有两个读者 “同时” 进行,如 1进程 判断 count == 0 后,在进行 P(rw) 之前切换到 2进程,此时 2进程 同样可以 判断 count == 0 ,进行 P(rw) 操作使 rw = 0,等进程切回 1 时,1进程会被阻塞在 P 操作那。

    多增加一个互斥信号量:

    但是仍然存在 写进程饿死 的问题,再增加一个信号量:

  • 重要考点:

● 哲学家进餐问题

  • 问题描述:

  • 问题分析:

  • 实现:

    每个哲学家吃饭前依次拿起左、右两支筷子

    如何防止死锁发生?

    或者:

  • 重要考点:

 

5. 管程

引入管程的原因:

  • 管程的定义

    有点像 面向对象中的类

  • 管程的基本特征

● 拓展1:用管程解决生产者消费者问题

引入管程的目的是更方便地实现进程互斥和同步:

● 拓展2:Java中类似管程的机制


 

四、死锁

1. 死锁的概念

  • 什么是死锁

    在并发环境下,各进程因竞争资源而造成的一种 相互等待对方手里资源,导致各进程都阻塞,都无法向前推进 的现象,就是 “死锁” 。

    发生死锁后,若无外力干涉,这些进程都将无法向前推进。

  • 死锁、饥饿、死循环的区别

    容易在选择中考察

  • 死锁产生的必要条件

    如果同类资源数> 1,则即使有循环等待,也未必发生死锁。(如上图所示)

    如果系统中每类资源都只有一个,那循环等待就是死锁的充分必要条件了。

  • 什么时候会发生死锁

  • 死锁的处理策略

 

 

2. 预防死锁(静态策略)

  • 破坏互斥条件

  • 破坏不剥夺条件

  • 破坏请求和保持条件

  • 破坏循环等待条件

 

 

3. 避免死锁(动态策略)

银行家算法

本节重要

什么是安全序列

例:

Ⅰ、若B还想借30亿

此时借给B的30亿是不安全的…

Ⅱ、若A还想借20亿

如上答应A的请求,按 T -> B -> A 的顺序借钱是 OK 的;按 A -> T -> B 的顺序也 OK。

所以借给A的20亿是安全的…


  • 安全序列

  • 安全状态

    如在上例 借给B 30亿后是不安全的,如果BAT没有提出再借20亿的请求,虽然系统处于不安全状态,但是还未发生死锁。(该点容易考察选择题

    因此可以在 资源分配之前预先判断这次分配是否会导致系统进入不安全状态,以此决定是否答应资源分配请求。(这也是 银行家算法 的核心思想)

 

银行家算法

  • 例子说明:

1)资源总数(10,5,7),剩余可用资源(3,3,2)

将剩余可用资源与每个进程最多还需多少资源进行比对:

2)资源总数(10,5,7),剩余可用资源(5,3,2)

重新进行新一轮比对:

3)资源总数(10,5,7),剩余可用资源(7,4,3)


实际做题(手算)方法:


找不到安全序列的例子:

一开始资源总数(10,5,7),剩余(3,3,2)

 

  • 代码实现思路

其中:

① 表示判断此次 i 申请的资源是否大于 i 所承诺的要申请的最大资源的数量;

② 表示判断系统中剩余的资源是否能满足此次 i 申请的资源;

③ 改变了三组数据,上例中执行第③步后修改如下:

 

  • 知识回顾与重要考点

 

4. 死锁检测和解除

死锁的检测



检测:(例)

eg:

死锁的解除

如图中P3未连着边,P3不是死锁进程,P1、P2是处于死锁的进程

解除死锁的主要方法:

1、资源剥夺法

不能挂起P3(因为不是死锁进程)
2、 撤销进程法 3、 进程回退法

如何决定 “对谁动手”:

其中第5点优先牺牲批处理式

 

如何解除一般只会在选择题中考察

你可能感兴趣的:(王道408,其他)