课堂笔记:操作系统

前言

我的博客:bdsnake.top
教材:

操作系统 孟庆昌

参考文档:

第一章:操作系统引论

操作系统(Operating System):是计算机用户和计算机硬件之间的终结程序

计算机系统概述

  • 计算机系统是由硬件和软件组成的
  • 硬件是软件建立活动的基础,软件是硬件功能的扩充
  • 计算机硬件结构:由CPU、内存和若干IO设备组成,他们由系统总线连接在一起,实现彼此通信

image-20220830141953217

处理器

CPU工作的基本周期
  • 从内存中提取指令
  • 对指令译码
  • 最后执行指令
所有CPU都包含某些寄存器

(寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。)

  • 通用寄存器
  • 专用寄存器
  • 程序计数器
  • 栈指针
  • PSW(程序状态字)
两种处理机执行状态
  • 核心态(Kernel Mode):运行操作系统程序
  • 用户态(User Mode):运行用户程序

分两种状态的原因:用于保护操作系统,用户没有权限

  • 处于用户态执行时,进程所能访问的内存空间和对象受到限制,其所处于占有的处理机是可被抢占的 ;
  • 而处于核心态执行中的进程,则能访问所有的内存空间和对象,且所占有的处理机是不允许被抢占的。

存储器

  • 寄存器
  • 高速缓存
  • 内存
  • 磁盘
  • 磁带

image-20220830143317685

IO设备

**设备组成:**通常用控制器和设备本身组成

  • 控制器
  • 设备
  • 设备驱动程序

**工作方式:**输入和输出的工作方式

  • 程序控制方式
  • 程序中断方式
  • DMA方式

什么是操作系统

操作系统概念

概念:
  1. 操作系统作为扩展机器
  2. 操作系统作为资源管理器
操作系统的主要工作:
  • 监视各种资源,随时记录它们的状态
  • 实时某种策略决定谁获得资源,何时获得,获得多少(决策,算法)
  • 分配资源供需求者使用(真正的分配资源)
  • 回收资源以便再分配
操作系统的用户观点和系统观点:

操作系统是控制和管理计算机系统内各种硬件和软件资源,有效的组织多道程序运行的系统软件,是用户和计算机之间的接口

操作系统的主要功能

  1. 存储管理功能

    内存分配,地址映射,内存保护,内存扩充

  2. 处理机管理功能

    作业和进程调度,进程控制和进程通信

  3. 设备管理功能

    缓冲区管理,设备分配,设备驱动和设备无关性

  4. 文件管理功能

    文件存储空间的管理,稳健操作的一般管理,目录管理,文件的读写管理和存取控制

  5. 用户接口

    命令界面、程序界面、图形界面

操作系统的地位

image-20220830150711884

操作系统的服务与服务方式

操作系统提供的服务

程序执行、I/O 操作、文件系统处理、通信、错误检测、资源分配、户管理、保护(了解)

操作系统的服务方式

1、系统调用

系统调用是操作系统提供的、与用户程序之间的接口,也就是操作系统提供给程序员的接口。它一般位于操作系统核心的最高层

系统调用类似于过程调用,系统调用是给用户使用的,写到用户程序里,用户程序想用就调

用户程序->执行系统调用(转为核心态)->用户程序(专为用户态)

2、系统程序

命令解释程序

1、内置方式

2、外置方式

操作系统的发展历程

操作系统的形成

  1. 手工操作阶段
  2. 早期批处理阶段
  3. 多道批处理系统
多道批处理系统
  • 多道程序设计的基本思想是在内存中同时存放多道程序,在管理程序的控制下交替地执行。这些作业共享CPU和系统中的其他资源。
  • 多道程序的这种交替运行称做并发执行
  • 在一段给定的时间内,计算机所能完成的总工作量(称为系统吞吐量)。

操作系统的发展

多道批处理系统->分时系统->实时系统->个人机系统->多处理器OS->网络OS->分布式OS->嵌入式OS

操作系统发展动力

  • 硬件技术更新
  • 应用需求增大

操作系统的类型

多道批处理系统

分时系统

实时系统

个人机(PC)系统

多处理器操作系统

嵌入式操作系统

网络操作系统

分布式操作系统

云计算操作系统

操作系统的特征

包括并发、共享、异步/不确定、虚拟性

并发

并发是指两个或多个活动在同一给定的时间间隔中进行。宏观概念。如CPU共享。

(并行性是指两个或多个事件在同一时刻发生;而并发性是指两个或多个事件在同一时间间隔内发生。 )

共享

共享是指计算机系统中的资源被多个进程所共用。如CPU、硬盘、内存、数据等。

共享分以下两种

**互斥地共享:**某进程申请资源、若空闲、分配、运行,下一个进程只能等待,直到前一进程释放资源。

**宏观上同时访问、微观上并发执行的共享:**如硬盘上文件的访问。

不确定性(异步性)

不确定性是指系统中各种事件发生顺序的不可预测性。(只有进程在获得所需的资源后方能执行,所以进程的执行通常都不是“一气呵成”,而是以“停停走走”的方式运行。)

虚拟性

一个物理实体映射为若干个对应的逻辑实体。虚拟是操作系统管理系统资源的重要手段,可提高资源利用率。

操作系统的结构

整体系统

  • 网状
  • OS是为数众多的一组过程的集合,各过程之间可以相互调用
  • 既庞大又杂乱。

层次式系统

上层调用下层。核心层。

例如,作业调度模块须调用进程控制模块;在为某作业创建一进程时,进程控制模块又须调用内存管理模块为新进程分配内存空间,可见,进程控制模块应在内存管理模块之上; 而作业调度模块又应在更高层。 下层应用程序模块是操作系统的内核 。

image-20220901092746716

模块化OS结构(附加内容)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QitCeIgN-1678290601824)(操作系统.assets/image-20220901092805441.png)]

虚拟机

以操作系统作为底层基本平台,在它上面安装并运行虚拟机软件,划分硬盘、内存等资源为几部分,这样物理机器通过共享资源的复件实现多个虚拟机器给多个用户。CMS(内容管理程序)相当于联系代理。VMM(虚拟机监督程序)分开多道程序和扩展机器的功能。

image-20220901092857051

优点:

  • 可运行多个操作系统
  • 系统更安全
  • 方便软件研制、开发、测试
  • 组建虚拟网络

缺点:

  • 硬件要求高
  • 实现复杂
  • 运行任务速度受影响。

目前常用的虚拟机软件: VMware Workstation\

客户-服务器系统

操作系统被划分成的各个服务器运行在用户态,微内核,安全

image-20220901093247274

  • 所有这些服务器(进程)都运行在用户态。
  • 微内核,用来处理客户和服务器之间的通信,即由内核来接收客户的请求,再将该请求送至相应的服务器;同时它也接收服务器的应答, 并将此应答回送给请求客户。

第二章:进程和线程

进程的定义

程序:就是一个指令序列

早期的计算机只支持单道程序:同一时间内只允许一个程序执行

后来出现了多道程序技术:

image-20220906142849611

为了方便操作系统管理,完成各程序的并发执行,引入了进程、进程实体的概念

进程的概念

进程:

我们都知道计算机的核心是CPU,它承担了所有的计算任务,而操作系统是计算机的管理者,它负责任务的调度,资源的分配和管理,统领整个计算机硬件;应用程序是具有某种功能的程序,程序是运行于操作系统之上的。

进程定义:进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程

举例说明:

image-20220906143756025

进程与程序的区别

(1)动态性

(2)并发性

(3)非对应性

(4)异步性

进程的特征

其实我感觉不如分成四大特征清晰。但是课上讲的这个

进程具有的特征:

  • **动态性:**进程是程序的一次执行过程,具有一定生命周期
  • **并发性:**任何进程都可以同其他进行一起并发执行;
  • **异步性:**指进程是按各自独立的、不可预知的速度向前推进的。
  • **调度性:**进程是被调度运行的单位,也是申请资源的单位。
  • **结构性:**程序 + 数据 + PCB
  • **独立性:**各进程的地址空间相互独立。进程实体是一个能够独立运行、独立被分配资源和独立接受调度的基本单位。

进程的状态与组成

进程的状态及其转换

  • 进程是程序的一次执行。在这个执行过程中,有时进程正在被CPU处理,有时又需要等待CPU服务
  • 可见,进程的状态是会有各种变化。为了方便对各个进程的管理,操作系统需要将进程合理地划分为几种状态。

在这里插入图片描述

在这里插入图片描述

状态的转移

在这里插入图片描述

  1. 运行态→阻塞态是种进程自身做出的主动行为
  2. 阻塞态→就绪态是不是进程自身能控制的,是种被动行为
  3. 注意:不能由阻塞态直接转换为运行态,也不能由就绪态直接转换为阻塞态(因为进入阻塞态是进程主动请求的,必然需要进程在运行时才能发出这种请求)

进程描述

进程映像
  • 一个或一组被执行的程序。
  • 与程序相关联的局部变量、全局变量等。
  • PCB:用于描述进程当前的状态、本身的特性、对资源的占用及调度信息等。
  • 栈:用来保存过程调用和相互传递参数的踪迹

image-20220906151626833

进程控制块的组成
  • 进程控制块是由OS维护的用来记录进程相关信息的一块内存。
  • 进程控制块是进程组成中最关键的部分,其中含有进程的描述信息和控制信息,是进程动态特性的集中反映,是系统对进程施行识别和控制的依据。

组成:

  • 进程描述信息
    • 进程名
      • 唯一的标志对应进程的一个标志符或数字。
      • 进程标识符:外部标志
      • 进程标识号(process ID):内部标志
  • 处理器状态信息(现场保护区)
    • 处理器寄存器内容
  • 进程控制信息
    • 特征信息 进程当前状态 调度优先级(priority) 通信信息 资源占用信息 进程实体信息 族系关系 其他信息

image-20220906151802651

进程控制块的作用
  1. 每个进程有唯一的进程控制块。
  2. 操作系统根据PCB对进程实施控制和管理。
  3. 进程的动态、并发特征是利用PCB表现出来的。
  4. PCB是进程存在的唯一标志

进程队列

image-20220906151941044

image-20220906151949296

image-20220906151958168

进程管理

进程的创建

  1. 为新进程分配一个唯一的进程标识号,并申请一个空白的PCB(PCB是有限的)。若PCB申请失败,则创建失败。
  2. 为进程分配资源,为新进程的程序和数据及用户栈分配必要的内存空间(在PCB中体现)。注意,若资源不足(如内存空间),则并不是创建失败,而是处于阻塞态,等待内存资源。
  3. 初始化PCB,主要包括初始化标志信息、初始化处理机状态信息和初始化处理机控制信息,以及设置进程的优先级等。
  4. 若进程就绪队列能够接纳新进程,则将新进程插入就绪队列,等待被调度运行。

进程的中止

  1. 找到指定进程的PCB
  2. 终止该进程的运行
  3. 回收该进程所占用的全部资源
  4. 终止其所有子孙进程,回收它们所占用的全部资源。
  5. 将被终止进程的PCB从原来队列中摘走

进程的阻塞

  1. 立即停止当前进程的执行
  2. 现行进程的CPU现场保存
  3. 现行状态由“运行”改为“阻塞”
  4. 转到进程调度程序

进程唤醒

  1. 把阻塞进程从相应的阻塞队列中摘下。
  2. 将现行状态改为就绪状态,然后把该进程插入就绪队列中。
  3. 如果被唤醒的进程比当前运行进程的优先级更高,则设置重新调度标志。

线程

线程概念

**线程(Thread)**是进程中实施调度和分派的基本单位

线程的组成

每个线程有一个thread结构,即线程控制块,用于保存自己私有的信息,主要由以下4个基本部分组成:

  • 一个唯一的线程标识符
  • 描述处理器工作情况的一组寄存器的内容
  • 每个thread结构有两个栈指针,一个指向核心栈,一个指向用户栈,核心态使用核心栈,用户态使用用户栈
  • 一个私有存储区,存放现场保护信息和其他与该线程相关的统计信息

image-20220913165038573

  • 线程必须在某个进程内执行
  • 一个进程可以包含一个线程或多个线程
线程的状态
  • 运行状态:
  • 就绪状态:
  • 阻塞状态:
  • 终止状态:

线程的管理

  • 线程创建
  • 线程终止
  • 线程等待
  • 线程让权
线程和进程的关系

① 一个进程可以有多个线程,但至少要有一个线程;而一个线程只能在一个进程的地址空间内活动。

② 资源分配给进程,同一进程的所有线程共享该进程的所有资源。

③ 处理机分配给线程,即真正在处理机上运行的是线程。

④ 线程在执行过程中需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。

线程的好处

① 易于调度。

② 提高并发性。

③ 开销少。

④ 利于充分发挥多处理器的功能。

在用户空间实现线程

在用户空间实现线程的优点

① 线程切换速度很快。

② 调度算法可以是应用程序专用的。

③ 用户级线程可以运行在任何操作系统上,包括不支持线程机制的操作系统。

用户级线程的主要缺点

① 系统调用的阻塞问题。

② 在单纯用户级线程方式中,多线程应用程序不具有多处理器的优点。

在核心空间实现线程

①在多处理器系统中,核心可以同时调度同一进程的多个线程;

② 如果一个进程的某个线程阻塞了,核心可以调度同一个进程的另一个线程。

  • 优点是,核心线程本身也可以是多线程的。
  • 缺点,主要是控制转移开销大。

image-20220913165347550

组合方式

image-20220913165423695

image-20220913165429574

image-20220913165434398

2.5:进程的互斥与同步

程间的相互关系分为3种

  • 互斥

    多个进程无合作关系,竞争资源

  • 同步

    多个进程共同完成任务,不知道对方的名字,但知道对方的作用

  • 通信

    高级通信,上面两个上低级通信

2.5.1: 进程的同步和互斥

同步:同步进程通过共享资源来协调活动,在执行时间的次序上有一定约束。虽然彼此不直接知道对方的名字,但知道对方的存在和作用。在协调动作的情况下,多个进程可以共同完成一项任务。

例如:卡片读写:读卡器->缓存1->缓存2->打印机。 接力跑

**互斥:**在逻辑上这两个进程本来完全独立,毫无关系,只是由于竞争同一个物理资源而相互制约。它们的运行不具有时间次序的特征。

例如:交叉路口争用车道;

2.5.2: 临界资源与临界区

临界资源

一次仅允许一个进程使用的资源称为临界资源。

宿舍电话、打印机、内存变量、指针、数组都是临界资源。

临界区

在每个进程中访问临界资源的那段程序叫做临界区。

为保证进程互斥地使用临界资源,一次只允许一个进程进入临界区。

进程互斥进入临界区的模式:

  • 进入前要申请
  • 获准后方可进入
  • 执行后要退出

进程的一般结构:

image-20220913170011923

入口区与退出区十分重要

2.5.3: 互斥实现方式

  1. 硬件方法
    • 禁止中断
    • 专用机器指令
  2. 软件方法
    • 置锁变量法
    • 信号量法

重点和难点是信号量法

禁止中断
  • 进入临界区后禁止中断->执行临界区代码->离开临界区前启用中断
  • 禁止中断,即CPU的执行不被打扰,更不会切换到其他进程,该进程可以放心地执行。
  • 简单的说就是这段操作很重要,谁也不能暂停我把资源分给别人

缺点:

一旦某个进程关闭中断后,如果不再开放中断,系统可能因此而终止。

专用机器指令

**TSL指令:**Test and Set Lock

image-20220913170406972

为每类临界区设置一把锁,该锁有打开和关闭两状态

进程执行临界区程序的操作步骤

  • 关锁
  • 执行临界区程序
  • 开锁

但是避免不了忙式等待对资源的占用

置锁变量法

类似于指令

image-20220913170619164

image-20220913170708644

注:lock与unlock为原子操作,不可分割

但是避免不了忙式等待对资源的占用

信号量法(重难点)

实现有三种

  1. 整型信号量——存在“忙等”问题
  2. 结构型信号量——解决“忙等”问题
  3. 二值信号量——结构型信号量的特殊情况

image-20220913170821663

其实和置锁变量法一样

  • 引入结构型信号量——解决忙等问题。
  • 结构型信号量一般是由两个成员组成的数据结构。
    • 每个信号量s含有一个整数值s.value(计数)
    • 还有一个进程等待队列s.list,其中是阻塞在该信号量的各个进程的标识(PCB)
typedef struct{
            int value;               //整型变量
            struct PCB *list;   //指向PCB的指针
        } semaphore;

引入一个等待队列

操作限制:

  1. 信号量(表示空闲资源总数)可以赋初值,且初值为非负数。
  2. 信号量的值可以修改,但只能由P和V操作来访问——作为OS核心代码执行,不受进程调度的打断。

P操作(请求调用资源)

     void P(semaphore S)
    {
            S.value--;         //表示申请一个资源;

            if(S.value<0)    //表示没有空闲资源;
            {
                 把这个进程加到S.list队列;
                 block( )//没有空闲资源,进程阻塞等待
             }
     }

V操作(释放资源)

         void V(semaphore S)
        {
                      S.value++//表示释放一个资源;
                      if(S.value<=0)    //有进程处于阻塞状态;
                     {
                           从S.list队列中移走进程Q;(唤醒队头进程)
                           wakeup(Q)}
          }

2.5.4: 信号量

信号量S.value的含义:

  • s>0时,表示该类可用资源的数量;
  • **s=0时,**表示没有该类可用资源;
  • **s<=0时,**表示没有该类资源可供分配,请求资源的进程将被阻塞在相应的信号量的等待队列中。s的绝对值 = 该信号量上等待的进程数。

image-20220913171255049

  • 每执行一次P操作,意味着请求分配一个单位的该类资源给执行P操作的进程,S:=S-1。 若无可用资源,进程阻塞等待。
  • 每执行一次V操作,意味着进程释放一个单位的该类可用资源,S:=S+1。 若有阻塞等待的进程,则唤醒它,转入就绪队列。

2.5.5: 信号量的一般应用

用信号量实现互斥

例如:通过缓冲区将文件写入磁盘

image-20220913175243844

供者和用者的关系

  • 缓冲区空,则供者把信息传入缓冲区,此时用者不能操作(阻塞)
  • 缓冲区满,则用者从缓冲区取数处理,此时供者不能操作(阻塞)

实现思路

  • 供者和用者间要交换两个消息:缓冲区空和缓冲区满的状态。
  • 设置两个信号量
    • S1表示缓冲区是否空( 1表示空,0表示不空)
    • S2表示缓冲区是否满( 1表示满,0表示不满)
    • 规定S1和S2的初值分别为1和0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t0GZQfLW-1678290601831)(操作系统.assets/image-20220913175503029.png)]

解释:S1代表缓冲区为空的信号,S2代表缓冲区为满的信号,下面是执行步骤

  1. 执行PS1 此时s1=0 s2=0
  2. 执行完临界区后执行VS2 此时s1=0 s2=1
  3. 执行PS2 此时s1=0 s2=0
  4. 执行完临界区后执行VS1 此时s1=1 s2=0
  5. 如此循环往复

以这种思路,如果有三个步骤,A->B->C,则需要分配两对S满与S空

经典进程同步问题

生产者-消费者问题

问题描述

问题表述如下:

一组生产者进程和一组消费者进程(设每组有多个进程)通过缓冲区发生联系。

生产者进程将生产的产品(数据、消息等)送入缓冲区,消费者进程从中取出产品。

假定缓冲区共有N个,把它们设想成一个环形缓冲池。

image-20220915110436399

为了使这两类进程协调工作,防止盲目的生产和消费,它们应满足如下同步条件:

  • 任一时刻所有生产者存放产品的单元数不能超过缓冲区的总容量(N)。
  • 所有消费者取出产品的总量不能超过所有生产者当前生产产品的总量。
  • 任何时刻只能有一个进程可对共享缓冲区进行操作。
解题思路

在上节课读写磁盘例子中,应用了empty和full两个信号量实现了互斥,而本题与上节课相比,只是多了一个缓冲区,所以我们只需要再多设置一个互斥信号量,保证每次只有一个人使用缓冲区即可,full和empty仍采用读写磁盘的思路

解题步骤

为了使两类进程实现同步操作,设置三个信号量:

  • empty:表示可供使用的空缓冲区数,初值为N。
  • full:表示放有产品的缓冲区数,初值为0。
  • mutex:互斥信号量,初值为1,保证任何时候只有一个进程使用缓冲区。

image-20220915110837059

不可以交换位置,先做empty和full的请求,是先问一下有没有我需要的资源,如果有我再尝试独占临界区,

如果先占临界区,占完发现没有我要的资源,那就死锁了

注意要点:

  1. 每个程序中先P(mutex),后V(mutex),二者要成对出现,二者中间为临界区;
  2. 对同步信号量full和empty的P、V操作同样必须成对出现,但它们分别位于不同的程序中;
  3. 无论是生产者、还是消费者,两个P操作的次序不能颠倒:应先执行同步信号量的P操作,再执行互斥信号量的P操作,否则可能造成死锁。
拓展题

设有无穷多个信息,输入进程把信息逐个写入缓冲区,输出进程逐个从缓冲区取走信息。设缓冲区是无穷大的。

输入/输出进程读写缓冲区需要何条件?

设信号量并说明其含义,给出初值。

用P、V操作实现两组进程的算法。

与典例区别为拓展区无限大,所以生产者不用考虑是否有空缓存,但是消费者仍需考虑是否有满缓存,因此是再典例基础上去掉关于empty的操作

系统中有多个生产者进程和多个消费者进程,共享一个能存放1000件产品的环形缓冲区(初始为空)。当缓冲区未满时,生产者进程可以放入其生产的一件产品,否则等待;当缓冲区未空时,消费者进程可以从缓冲区取走一件产品,否则等待。要求一个消费者进程从缓冲区连续取10件产品后,其他消费者进程才可以取产品。

请使用P、V操作实现进程间的互斥与同步算法,要求写出完整的过程,并说明所用信号量的含义和初值。

与典例区别为限定消费者连取10件退出,所以再加一个mutex

image-20220915111739846

读者-写者问题

问题描述
  • 读者-写者问题也是一个著名的进程互斥访问有限资源的同步问题。
  • 例如,一个航班预订系统有一个大型数据库,很多竞争进程要对它进行读、写。允许多个进程同时读该数据库,但是在任何时候如果有一个进程写(即修改)数据库,那么就不允许其他进程访问它—— 既不允许写,也不允许读。
  • 数据库中,任一时刻最多只允许有一个“写者”,而“读者”则允许有多个
  • image-20220915111824184
解题思路

image-20220915111850658

image-20220915111905028

image-20220915111918067

解题步骤

第一种:读者优先写者

  • wmutex:写互斥信号量,用于保证一个写者与其他读者/写者互斥地访问共享资源,初值为1。
  • readcount:读计数器,用于统计数据库中读者数量,是整型变量,初值为0。
  • rmutex:读互斥信号量,用于读者互斥地访问readcount,初值为1。

实现思路就是第一个读的人把写锁打开,不让写者写,直到没有人读了再打开写锁,允许执行写操作

image-20220915112019944

第二种:读者写者按到达顺序访问数据库

实现思路:增加一个互斥信号量w ,实现当写进程到达时封锁后续的读进程。需要在读者和写者进程中各增加一对P(w)和V(w)操作,用于控制进程按照申请顺序访问。

  • wmutex:写互斥信号量,用于保证一个写者与其他读者/写者互斥地访问共享资源,初值为1。
  • readcount:读计数器,用于统计数据库中读者数量,是整型变量,初值为0。
  • rmutex:读互斥信号量,用于读者互斥地访问readcount,初值为1。
  • w:互斥信号量,用于控制进程按照进程申请顺序访问,初值为1。

image-20220915112228523

第三种,写者优先读者

参考第一种,类似

拓展

假定一个阅览室可容纳一百人,读者进入和离开阅览室时都必须在阅览室门口的登记表上做标识(进入时登记,离开时去掉登记),而且每次只允许一人登记或去掉登记。

应设置几类进程?

用P、V操作实现同步算法。

分析:

每个读者对应一个进程,他们是同类进程。每个读者的动作都包括:

  • 申请阅览室的空位;
  • 入室前查表、登记;
  • 进入室内,阅读书籍;
  • 出室时删除登记;
  • 阅览室多出一个空位。

设置信号量

  • S——座位情况,初值为100;
  • mutex——互斥使用登记表,初值为1。

image-20220915112409024

哲学家进餐为题

问题描述

image-20220915112431082

解题思路

简单的解决办法:五根筷子对应信号量数组chopstick[5],初值为1。第i个哲学家的进餐过程可描述为:

 While(true){
		think;
		P(chopstick[i]);
		P(chopstick[(i+1)mod5]);
		eat;
		V(chopstick[i]);
		V(chopstick[(i+1)mod5]);  }
  • 上述算法可保证相邻的两个哲学家不能同时进餐。 但存在死锁隐患:
  • 如果五个哲学家同时拿起各自左边的筷子,又试图拿右边的,则产生死锁。

解决死锁的方法

  1. 最多只允许4个哲学家同时拿筷子,从而保证有一人能够进餐。
  2. 仅当某哲学家左右两边的筷子都可用时,才允许他拿筷子。
  3. 将哲学家编号,要求奇数号的哲学家先拿左边筷子,偶数号哲学家先拿右边筷子。
解题步骤

1、最多只允许4个哲学家同时拿筷子,从而保证有一人能够进餐

typedef struct{                /* 定义结构型信号量 */
           int value;
           struct PCB *list;
   } semaphore;

 semaphore chopstick[5] ={1,1,1,1,1} ;    
 semaphore count=4;  /*允许同时拿筷子准备进餐的人数*/
 int I;                             /* 代表第I个哲学家*/

While(true){
		think;
		P(count);//信号量count表示允许同时拿筷子准备进餐的哲学家数量,将其看作一种资源。使用前申请,使用后释放。
          P(chopstick[I]);
		P(chopstick[(I+1)mod5]);
		Eat;
		V(chopstick[I]);
		V(chopstick[(I+1)mod5]);  
          V(count);
 }

2、仅当某哲学家左右两边的筷子都可用时,才允许他拿筷子。

必须让哲学家拿起2根筷子的操作是不可分割的,如果不能拿起2根筷子则阻塞等待,直到确定能拿起2根筷子则结束等待。

  • 对每个哲学家设置信号量S[i],代表是否能够拿起两根筷子,即是否具备进餐条件,初值都是0。
  • 对每个哲学家设一个整型变量state,用于存储状态,则5个哲学家对应一个整型数组state[i]。 每个哲学家都有三种状态:thinking、hungry、eating。
  • 如果当前哲学家是hungry,左邻、右邻都不在eating状态,则当前哲学家i可以转入eating状态,即进行V(S[i])操作。 对哲学家状态的测试和改变需要互斥操作,用mutex控制。
#define  N    5
#define  LEFT  (i-1)%N
#define  RIGHT  (i+1)%N
#define  THINKING  0
#define  HUNGRY   1
#define  EATING   2
  typedef struct{                /* 定义结构型信号量 */
           int value;
           struct PCB *list;
   }semaphore;
   int state[N];
   semaphore mutex=1;     /* 互斥进入临界区  */
   semaphore s[N]=0;        /* 每位哲学家一个信号量,代表是否具备进餐的条件,信号量初值都是0,表示最初都不具备进餐条件,需要测试完才知道是否具备条件 */

void philosopher(int i)
{
         while(TRUE){
               think();            		/* 哲学家在思考问题 */
               take_chopstick(i);              /* 拿到两根筷子或者等待 */ 
               eat();              		/* 进餐 */
               put_chopstick(i);                /* 把筷子放回原处 */
          }
}

void take_chopstick(int i)
{
            P(mutex);
            state[i]=HUNGRY;
            test(i);                                /* 试图拿两根筷子 */        
            V(mutex);
            P(s[i]);         /*具备资源,则使用资源,否则等待资源可用*/
}    

void put_chopstick(int i)
{    
          P(mutex);
          state[i]=THINKING;              
          test(LEFT);            	/* 查看左邻,现在能否进餐 */
          test(RIGHT);         	/* 查看右邻,现在能否进餐 */
          V(mutex);    
 }

void test(int i)
{       
if(state[i]==HUNGRY &&   state[LEFT]!=EATING && state[RIGHT]!=EATING)
        {
               state[i]=EATING;
               V (s[i] );
         }
 }

管程

前言

  • 用信号量机制解决同步问题,要设置很多信号量,并使用大量的P、V操作,还要仔细安排P操作的顺序,以防止死锁。
  • 为了解决此问题,Brinch Hansen和Hoare分别在20世纪70年代中期提出管程高级同步机制。
  • 主要掌握:管程的定义、管程的组成、管程的基本特性

定义

  • 定义1:系统中的各种硬件资源和软件资源均可用数据结构抽象地描述其资源特性,即用少量信息和对该资源所执行的操作来表征该资源,而忽略它们的内部结构和实现细节。
  • 定义2:一个管程定义一个数据结构和能为并发进程在其上执行的一组操作,这组操作能使进程同步和改变管程中的数据。

组成

  • 管程名称
  • 局部于管程的共享数据结构的说明
  • 对该数据结构进行操作的一组过程
  • 对共享数据赋初值的语句

image-20220920144300575

特性

  • 管程内部的局部数据变量只能被管程内定义的过程所访问,不能被管程外面声明的过程直接访问。
  • 进程要想进入管程,必须调用管程内的某个过程。
  • 一次只能有一个进程在管程内执行,而其余调用该管程的进程都被挂起,等待该管程成为可用的。即管程能有效地实现互斥。

前两个特性类似于面向对象程序设计中的类

管程的实现

管程能自动地实现对临界区的互斥;
管程通过条件变量+原语实现同步。

  • **两个条件变量:**x,y
  • **同步操作原语:**wait和signal
  • **wait(x):**挂起等待条件x的调用进程,释放相应的管程,以便供其他进程使用。
  • **signal(x):**恢复执行先前因在条件x上执行wait而挂起的那个进程。
  • 注意:x和y不是计数器,也不能像信号量那样积累信号。当x上没有等待进程时,执行signal(x)所发送的信号将丢失。因此规定wait(x)必须在signal(x)之前。

image-20220920144823399

管程的特征

  • **模块化:**一个管程是一个基本程序单位,可以单独编译;
  • **抽象数据类型:**管程是一种特殊的数据类型,不仅有数据,还有对数据进行操作的代码;
  • **信息隐藏:**管程是半透明的,管程内部的过程(函数)实现了某些功能,这些功能如何实现,外部不可见;
  • **封装性:**管程中定义的对共享变量的所有操作都局限在管程中,外部只能通过调用管程的某些函数来间接访问这些变量。

管程的缺点

  • C、Pascal等多数编程语言都不支持管程。
  • 要求编译程序必须能识别管程,并用某种方式实现互斥。
  • 编译程序如何知道哪些过程属于管程内部,哪些不属于管程,实现有难度。

进程通信

前言

  • 进程通信就是进程间的信息交换。
  • 重点掌握:
    • 什么是低级通信、高级通信
    • 高级通信有哪几类

低级通信与高级通信

  • 低级通信:只能传递状态和整数值(控制信息),包括进程互斥和同步所采用的信号量和管程机制。
  • 优点:速度快
  • 缺点
    • 传送信息量小,效率低,每次通信传递的信息量固定,若传递较多信息则需要进行多次通信。
    • 编程复杂,用户直接实现通信的细节,容易出错。

  • 高级通信:能够传送任意数量的数据
  • 主要方式:
    共享存储区
    消息传递
    管道文件

三种高级通信方式

共享存储器方式
  • 共享存储器方式是在内存中分配一片空间作为共享存储区。需要进行通信的各个进程把共享存储区附加到自己的地址空间中,然后就对可以对共享区中的数据进行读或写。如果不需要,可以取消。
  • 需要使用同步互斥工具(如PV操作)对共享空间的读写进行控制。
消息传递方式
  • 以消息(Message)为单位在进程间进行数据交换。
  • 进程通过操作系统提供的发送消息(send)和接收消息(receive)两个原语进行数据交换。

两种方式

  • **直接通信方式:**发送进程直接将消息挂在接收进程的消息缓冲队列上,接收进程从消息缓冲队列中得到消息。
  • 间接通信方式:发送进程将消息送到称做信箱的中间设施上,接收进程从信箱中取得消息,也称为信箱通信方式。(有人往信箱放,有人从信箱取)

间接通信方式广泛应用于计算机网络中,相应的通信系统称为电子邮件系统。

管道文件方式(PIPE文件)
  • 管道文件也称管道线,它是连接两个命令的一个打开文件。一个命令向该文件中写入数据,称做写者;另一个命令从该文件中读出数据,称作读者。

    $ cat file1 | more # cat 是显示文件内容的命令,|more代表使用了一个打开的管道文件,先由cat file1 往文件写数据,由more文件读数据
    
    • 分屏显示文件file1的内容。
  • 系统自动处理二者间的同步、调度和缓冲。

  • 为了协调双方的通信,管道机制必须提供以下三方面的协调能力:

    • **互斥,**即当一个进程正在对pipe执行读/写操作时,其它(另一)进程必须等待。
    • **同步,**指当写(输入)进程把一定数量(如4 KB)的数据写入pipe,便去睡眠等待,直到读(输出)进程取走数据后再把它唤醒。当读进程读一空pipe时,也应睡眠等待,直至写进程将数据写入管道后才将之唤醒。
    • 确定对方是否存在,只有确定了对方已存在时才能进行通信。

消息传递系统

  • 允许进程彼此进行通信,而不必借助于共享数据
  • 提供两个原语(系统调用)send和receive:
    send (destination, message)
    receive (source, message)
消息传递系统设计

涉及同步、寻址、格式和排队规则等多项问题

  • 同步

  • 寻址

    • 直接通信方式(对称寻址|非对称寻址)
    • 间接通信方式——信箱
      公用信箱
      共享信箱
      私有信箱
  • 消息格式

    取决于消息机制的目标和在什么系统上运行

  • 排队规则

    先进先出
    优先权法
    接收方挑选

image-20220920150105882

**用消息传递方式解决生产者-消费者问题 **

#define N 100/* 缓冲区个数 */
 void producer(void)
 {      int item;
         message m;/* 消息缓冲区 */
         while (TRUE){
             item=produce_item()/* 生成一些数据放入缓冲区 */
             receive(consumer,&m);/* 等待一条空消息到达 */
             build_message(&m,item);/* 构造一条可供发送的消息 */
             send(consumer,&m);	/* 向消费者发送一个数据项 */
         }
  }
  void consumer(void)
  {     int item,i;
         message m;
         for (i=0;i<N;i++)
             send(producer,&m);/* 发送N条空消息 */
         while (TRUE){
             receive(producer,&m); /* 接收一条包含数据的消息 */
             item=extract_item(&m);/* 从消息中提取数据项 */
             send(producer,&m);/* 发回空消息作为应答 */
             consume_item(item);/* 使用数据项进行操作 */
         }
  }

客户-服务器系统中的通信

socket
  • 好像一条通信线两端的接插口。
  • 一对进程通过网络进行通信要用一对socket,每个进程一个。
  • 三个要素:
    1. 网络地址表明一个socket用于哪种网络。
    2. 连接类型表明网络通信所遵循的模式,主要分为“有连接”和“无连接”模式。
    3. 网络规程表明具体网络的规程。一般,网络地址和连接类型结合在一起就基本上确定了适用的规程。

image-20220920150806154

远程过程调用(RPC)
  • 远程过程调用(Remote Procedure Call, RPC)是远程服务的一种最常见的形式。

  • 远程过程调用的思想:

    允许程序调用另外机器上的过程。

具体步骤:

  1. 客户过程调用客户代理
  2. 客户代理构造一个消息,并且陷入内核
  3. 本地内核发送消息给远程内核
  4. 远程内核把消息送给服务器代理
  5. 服务器代理从信包中取出参数,并调用服务器
  6. 服务器完成相应的服务,并将结果送给服务器代理
  7. 服务器代理将结果打包形成消息,并且陷入内核
  8. 远程内核发送消息给客户机内核
  9. 客户机内核把消息传给客户代理
  10. 客户代理取出结果,返回给客户的调用程序

image-20220920150930411

第三章:死锁

资源

概念:计算机系统中有很多一次只能由一个进程使用的资源。

  • 硬件资源:硬件设备(打印机、刻录机、扫描仪等)
  • 软件资源:一组信息(加锁记录、信号量、系统表格等)

资源使用模式

  1. 申请
  2. 使用
  3. 释放

申请数量 ≤ 可用资源的总量,否则阻塞

资源分类

  1. 可剥夺资源
  2. 不可剥夺资源

**可剥夺资源:**其他进程可以从拥有资源的进程那里把它剥夺过去为己所用,且不会产生任何不良影响。(例如,内存就是可剥夺资源。A占有打印机并申请内存,B占有内存并申请打印机,A可以剥夺B的内存)

**不可剥夺资源:**不能从当前占有它的进程那里强行抢占的资源,必须由拥有者自动释放,否则会引起相关计算的失效。(进程A刻录光盘,突然把刻录机分给进程B使用。)

死锁不可剥夺资源有关

死锁概念

什么是死锁

死锁定义:所谓死锁,是指在一个进程集合中的每个进程都在等待仅由该集合中的另一个进程才能引发的事件而无限期地僵持下去的局面。(系统中多个进程无限地等待永远不会发生的状态)

image-20220922104227324

产生死锁的原因:

  • 资源有限
  • 操作不当
    • 程序编写问题
    • 进程推进顺序不当

因操作顺序不当产生的死锁

举例说明

有两个进程A和B,竞争两个资源R和S,这两个资源都是不可剥夺资源

进程A                        进程B
           ……                          ……
         申请并占用R              申请并占用S
         申请并占用S              申请并占用R
           ……                          ……
         释放R                        释放S
         释放S                        释放R
           ……                          ……

A申请并占用R的同时B申请并占用S,此时RS都被占用,而AB进程都不能继续推进,产生死锁

是否产生死锁既取决于动态执行过程,也取决于应用程序的设计。改进程序,使进程A不必同时申请两个资源,将代码改为:

进程A 
	 ……
	 申请并占用R
	 …… 
	 释放R
     申请并占用S
     ……
	 释放S           

死锁的条件

当计算机系统同时具备下面4个必要条件时,会发生死锁

  1. 互斥条件

    征用的资源互斥使用

  2. 占有且等待条件

    每个进程都占有一定资源并等待其他资源

  3. 不可抢占条件

    占用的资源不可抢占

  4. 循环等待条件

    进程间在循环等待对方结束

只要有一个必要条件不满足,则死锁就可以排除。(这也是解决死锁的思路)

资源分配图

用圆圈表示每个进程,用方框表示每个资源类型,箭头指向进程表示占用资源,箭头指向资源表示申请资源

image-20220922105022338

环路与死锁

存在环路是死锁存在的必要条件但不是充分条件

image-20220922105147049

死锁的预防

破坏互斥条件

有些资源本身要求必须互斥访问,这是资源的固有属性,所以,用否定互斥条件的办法不能预防死锁。

破坏占有且等待条件

  • 一种办法是“空手”申请资源策略:

    不占有资源的时候,才能申请。

  • 一种办法是预分资源策略:

    静态分配:执行之前申请到全部资源

    预分资源策略的缺点:

    1. 很多情况下,进程执行前无法知道所需全部资源;
    2. 资源利用率降低;
    3. 降低了进程的并发性;
    4. 可能出现饥饿现象:无法得到众多进程争用的“紧俏”资源。

破坏不可抢占条件

隐式抢占方式(被抢)

如果一个进程占有某些资源,它还要申请被别的进程占有的资源,该进程就一定处于等待状态,则进程当前所占有的全部资源可被抢占。

抢占等待者的资源(去抢)

进程申请资源,如果没有可用,可以从等待进程那里抢占资源。

这些办法常用于资源状态易于保留和恢复的环境中,如CPU寄存器、内存,但不能用于打印机、磁带机等。

破坏循环等待条件

一种方法是实行资源有序分配策略。

  • 设R={r1, r2, …, rm}表示一组资源,定义一对一的函数F:R→N,式中N是一组自然数。

  • 所有进程对资源的申请严格按照序号递增的次序进行。

  • 例如: F(磁带机)= 1,F(磁盘机)= 5,F(打印机)= 12。

  • 又如:

    R1   R2   R3   R4   R5   R6   R7
    

    A * * *

    B * * *

    C * * * *

另一种方法:先弃大,再取小。

资源利用率和系统吞吐量都有所提高,但也存在两个缺点:

  • 限制了进程对资源的请求,同时给系统中所有资源合理编号也是件难事,并会增加系统开销;
  • 为了遵循按编号申请的次序,暂不使用的资源也需要提前申请,从而增加了进程对资源的占用时间。

死锁的避免

安全状态和安全状态

安全序列:

如果系统能按某个顺序为每个进程分配资源(不超过最大值)并能避免死锁,那么系统状态就是安全的,即如果存在一个安全序列,那么系统就处于安全状态。否则系统处于不安全状态

image-20220927142212755

死锁是不安全状态的特例,系统于不安全再辉煌台运行可能会产生死锁

安全状态示意

image-20220927143233669

不安全状态示意

image-20220927143329507

安全状态死锁

image-20220927144037799

环路与死锁:

如果每类资源的实体都只有一个,那么图中出现环路就说明死锁了。

如果每类资源的实体不止一个,那么资源分配图中出现环路并不表明一定出现死锁。

资源分配图中存在环路是死锁存在的必要条件,但不是充分条件。

资源分配的算法

分为单体和多体

  • 单体资源类

    系统中的资源都只有一个,可用资源分配图算法。

  • 多体资源类

    系统中的资源都有多个,可用银行家算法。

资源分配图算法

算法描述:设进程Pi申请资源rj,仅当申请边pi rj转换为赋给边且不会导致资源分配图中出现环路时,申请才可实现。

银行家算法

银行家算法的设计思想是:当用户申请一组资源时,系统必须做出判断;如果把这些资源分出去,系统是否还处于安全状态。若是,就可以分出这些资源;否则,该申请暂不予满足。

上面仅为概念,说的比较抽象,下面看例子

资源分配算法举例(感觉会考大题)

资源分配图算法(适用系统资源只有一个)

image-20220927150935101

如下图,若p2申请r2则构成环路,

image-20220927151002106

所以如果分配,则处于不安全状态

银行家算法(适用系统资源有多个)

image-20220927151523220

图中表的含义解释:

  • Max:代表某个进程P总共需要多少资源
  • Allocation:已经分配出去的资源
  • Need:代表还需要多少资源
  • Available:代表现在有多少资源

当满足某进程所需的所有资源后,可以执行进程并释放资源


死锁的检测与恢复

UNIX系统就摆烂,不避免死锁,只进行检测和恢复

由于死锁可能不常发生,而用死锁避免的算法可能又会产生不必要的消耗,所以现在我们有了一个新思路

任由死锁发生,系统需要做的是检测和恢复

死锁的检测同样分为单体和多体

死锁的检测与死锁的避免方法类似

  • 对单体资源类的死锁检测——等待图
  • 对多体资源类的死锁检测——检测算法(与安全性算法类似)

等待图

image-20220927152017931

  • 等待图:它是从资源分配图中去掉表示资源类的节点,且把相应边折叠在一起得到的。
  • 检测依据:当且仅当等待图中有环路,系统存在死锁。

检测算法

其实就是定期调用银行家算法,看看有没有发生死锁

image-20220927152548416

先释放p1 p3 然后给p4 p2 p5

例2:死锁情况

image-20220927152649708

检测的时机

  • 取决两个因素:
    • 死锁出现的频繁程度
    • 有多少个进程受死锁的影响
  • 检测时机
    • 有资源请求时就检测(这样就和死锁避免一样了,只要请求我就先看看会不会产生死锁)
    • 定时检测
    • CPU使用率低于规定下限值时,进行检测
      • 死锁涉及较多进程时,CPU经常闲置

死锁的恢复

主要有三种恢复方式:

  • 通过抢占资源实现恢复
  • 通过回退执行实现恢复
  • 通过杀掉进程实现恢复

抢占资源

  • 挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程,直至死锁环路被打破。
  • 注意:要防止被挂起的进程长时间得不到资源

回退执行

  • 让一个或多个进程回退到足以回避死锁的地步,进程回退时自愿释放资源而不是被剥夺。
  • 注意:要求系统保持进程的历史信息,设置还原点。

杀掉进程

  • 杀掉进程,回收资源:
    • 终止所有的死锁进程。
    • 一次终止一个进程,直至消除死锁环路。
  • 终止进程的选择依据:
    • 进程优先级;
    • 已运行时间,剩余时间;
    • 使用资源及资源类型;
    • 还需要多少资源?
    • 进程是交互式的,还是批处理程序?

"饥饿"状态

  • 在某些策略下,系统会出现这样一种情况:在可以预计的时间内,某个或某些进程永远得不到完成工作的机会,因为它们所需的资源总是被别的进程占有或抢占。这种状况称做“饥饿”或者“饿死”(Starvation)。
  • 饥饿不同于死锁:
    • 死锁的进程必定处于阻塞状态,而饥饿进程不一定被阻塞,可以在就绪状态;
    • 可以利用FCFS资源分配策略来避免饥饿。

处理死锁的综合方式

也就是把前面几种策略综合应用

三种方法比较

image-20220927153616327

第四章:处理器调度

调度的概念

调度:在同一时刻,有很多任务需要处理,由于资源有限,这些事情没法同时处理。处理机会以某种规则来决定处理这些任务的顺序。

一个作业从提交开始直到完成,一般经历三级调度

  • 高级调度(作业调度)

    其主要任务是按一定的原则从外存上处于后备队列的作业中挑选几个作业调入内存,给它们建立进程、分配必要的资源,并将它们放入就绪队列,以使它们获得竞争处理器的权利。

  • 中级调度(内存调度、进程挂起与兑换)

    不重要的挂起到外存,省内存

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

  • 低级调度(进程调度)

    其主要任务是按照某种方法和策略从就绪队列中选取一个进程,将处理器分配个它。进程调度是操作系统中最基本的一种调度,在一般的操作系统中都必须配置进程调度。进程调度的频率很高,一般几十毫秒一次。

三层调度的联系与对比

做什么调入发送在哪发送频率对进程状态的影响
高级调度(作业调度)按照某种规则,从后备队列中选择核实的作业将其调入内存,并为其创建进程外存-> 内存很低无-创建态–就绪态
中级调度(内存调度)按照某种规则,从挂起队列中选择合适的进程将其数据调入内存外存–内存中等挂起态–就绪态
低级调度(进程调度)按照某种规则,从就绪队列中选择一个进程为其分配处理机内存–CPU很高就绪态–运行态

进程调度时机、切换与过程

调度时机

  1. 当前进程运行结束
  2. 当前运行进程因某种原因从隐形状态进入阻塞状态
  3. 执行完系统调用等系统程序后返回用户进程,此时可以看成系统进程执行完毕,从而可以调度一个新的用户进程
  4. 在采用抢占调度方式的系统中,优先级更高的进程要求使用cpu,则使当前运行进程进入就绪队列
  5. 分时系统中,分配给该进程的时间片用完

进程调度过程

  1. 保存运行进程的现场信息(保存到PCB中)

进程调度的方式

当一个进程正在处理器上执行时,优先级更高的进程计入就绪队列,此时如何分配处理器?

分两种,抢占式非抢占式

  • 非抢占式
    • 一旦把CPU分给一个进程,该进程会保持CPU直到完成或转到等待状态
    • 适用于大多批处理系统,但不能用于分时系统和大多数实时系统

调度的基本准则

  • 面向系统的准则
    • CPU利用率
    • 系统吞吐量
  • 面向用户的准则
    • 周转时间
    • 就绪等待时间
    • 响应时间

周转时间

典型调度算法(出大题)

先来先服务法(FCFS)【非抢占】

举例:排队做核酸,不能插队

  • 非抢占式
  • 简单易于理解效率低
  • 有利于长作业,不利于短作业
  • 有利于CPU繁忙型作业(进程),不利于I/0繁忙型作业(进程)

短作业优先法(SJF)【非抢占】

所谓长短是指作业(进程)要求运行时间的多少

  • 实现思想

    当分配CPU时,选择所需时间最短的进程,短进程将越过长进程,跳到队里额头

  • 有利于缩小平均等待时间(类似于贪心算法)

  • 实现上有困难(要估计每个作业所需处理时间)

  • 对长作业不利

最短剩余时间优先法(SRTF)【抢占】

  • 实现思想

    新进程所需运行时间比当前运行进程还需的时间还要短,就夺取CPU的控制权

  • 平均等待时间比SJF还短

  • 缺点在于切换次数多,系统付出代价大

  • 不利于长作业

高响应比优先法(HRRF)【非抢占】

  • 实现思想
  • 响应比:(等待时间+要求服务时间)÷要求服务时间 = (w+s)/s = 1+w/s
    • w是作业等待处理机所需时间
    • s是作业要求的服务时间
    • 先挑选响应比高的
举例
作业到达时间要求服务时间
J108
J254
J376
J493

J1先运行,8s结束时,J2的响应比为1+3/4,J3为1+1/6,故J2先执行

优先级法(HPF)

从就绪队列李选出优先级最高的进程,让它在CPU上运行

确定进程优先级的方式有静态方式和动态方式两种

  • 动态
    • 随着等待时间的延长,优先级提高
    • 进程每执行一个时间片就降低其优先级(实现负反馈,防止长时间占用CPU

这种方法有抢占式和非抢占式

5个进程在0时刻同时到达系统,运用优先级调度算法,请给出调度顺序,优先数小,优先级高注意有时候给优先数有时候给优先级

进程运行时间优先数
P1103
P211
P324
P415
P552

因同时到达,不存在抢占问题,直接按优先级排序

P2 P5 P1 P3 P4

P1进程在0时刻同时到达系统,其余进程分别相差一个时间单位,运用优先级调度算法,分别采用非抢占式和抢占式,计算平均周转时间是多少?优先数小,优先级高

进程运行时间优先级
P1103
P211
P324
P415
P552
  • 非抢占式

    P1最先运行,P1运行完之后所有进程都到达了,然后再排序

    P1 P2 P5 P3 P4

  • 抢占式

    新进程到达时比较所有进程的优先级

    image-20220929100550930

时间片轮转法(RR)【抢占式】

  • 实现思想
    • 将系统中所有的就绪进程按照FCFS原则,排成一个队列。每次调度时将CPU分派给队首进程,让其执行一个时间片。
    • 在一个时间片结束时,发生时钟中断。调度程序据此暂停当前进程的执行,将其送到就绪队列的末尾,并通过上下文切换执行当前的队首进程。
    • 进程可以未使用完一个时间片,就出让CPU(如阻塞)。
  • 时间片轮转法(Round-Robin)主要用于分时系统中的进程调度。

举例

A,B,C,D同时到达,需运行时间为12,5,3,6个时间单位,试求时间片分别为1个和4个时间单位时,进程的运行情况?

image-20221004141646109

  • 进程的周转时间依赖于时间片的大小。

    image-20221004142115398

    如图当q>=6时退化为FCFS先来先服务策略

  • 时间片长度对算法的影响

    • 过长->退化为FCFS算法,进程在一个时间片内都执行完。
    • 过短->用户的一次请求需要多个时间片才能处理完,上下文切换次数增加。
    • 使单个时间片内多数进程能够完成它们的运行工作,平均周转时间会得到改进。
  • 时间片的大小直接影响轮转法的性能,对系统性能影响也很大。

  • 时间片长短的四个决定因素

    • 系统的响应时间

      在进程数目一定时,时间片的长短直接正比于系统对响应时间的要求。

    • 就绪队列中的进程数目

      当系统要求的响应时间一定时,时间片的大小反比于就绪队列中的进程数目。(进程数目少,时间片可以设置大一点;进程数目大,时间片可以设置小一点)

    • 进程的转换时间

      若执行进程调度时的转换时间为t,时间片为q,为保证系统开销不大于某个标准,应使比值t/q不大于某一数值,如1/10。

    • CPU运行指令速度

      CPU运行速度快,则时间片可以短些;反之,长些。

多级队列法(MQ)

  • 实现思想

    • 调度算法把就绪队列划分成几个单独的队列

    • 每个队列都有自己的调度算法。

    • 队列之间通常采用固定优先级的抢占式调度

      image-20221004152029999

      前面的队列全空了才能调后面的队列,如学生批处理进程正在运行,如果有一个批处理进程到达,则抢占当前进程的CPU

多级反馈队列法(MFQ)

  • 实现思想

    • 系统中设置多个就绪队列,每个队列对应一个优先级,优先级依次递减;
    • 每个队列都采用时间片轮转法,但时间片都不同,高优先级队列的时间片小,低优先级队列的时间大;
    • 新进程进入系统后,先放入第1个队列的末尾,如果在时间片内工作未完成,则转入下一个队列尾,依此类推;
    • 系统先运行第1个队列中的进程,若第1队列为空,才运行第2队列,依次类推。

    image-20221004152505173

总结比较

比较项目 算法FCFSSJFHRRFRRMFQ
调度方式非抢占式非抢占式非抢占式抢占式抢占式
优点公平,实现简单平均等待时间最少,效率最高兼顾长短作业兼顾长短作业兼顾长短作业,有较好的响应时间,可行性强
缺点不利于短作业和I/O繁忙型作业不利于长作业,可能会饥饿计算响应比的开销大平均等待时间长,上下文切换浪费时间
开销最小可能高可能高可能高
主要适用于作为其他算法的基础算法作业调度、批处理系统作业调度分时系统通用
**“**饥饿”问题可能可能

期末考题:

给出进程执行时间、到达时间、优先级,分析不同算法的运行过程,算出平均进程周转时间

image-20221004143904827

image-20221004145039964

注意如果题目改为ABCDE依次相差一个时间单位到达,时间片调度算法,需要考虑切换开销

此时不是简单地按ABCDE的顺序,如果考虑切换开销需要画出进程队列考虑问题

例如:B执行完毕时E到达,因为B切换到进程队列需要时间,而此时E到达,所以E先排进进程队列

线程调度

概述

  • 线程系统中,提供了进程和线程两级并行机制。
  • 因为线程的实现分为用户级和核心级,所以在多线程系统中,调度算法主要依据线程的实现而不同。

用户级线程

image-20221004154231883

核心级线程

image-20221004154249111

两者的特点

用户级线程调度与核心级线程调度的特点

  • 性能
    • 用户级线程切换可以用机器指令,速度快;核心级线程切换需要全部上下文切换,速度慢。
  • 阻塞
    • 在核心级线程方式下,一个线程因等待I/O而阻塞时,不会挂起整个进程;而用户级方式下会挂起整个进程。

实时调度

概述

  • 在实时系统中,有多个实时任务,每个任务都有其时间约束。

  • **实时调度:**满足实时任务各自时间约束条件的调度。

  • 实时任务通常与截止时间相关联

    • **开始截止时间:**实时任务最迟开始处理的时间
    • **完成截止时间:**实时任务最迟完成处理的时间

实时任务类型

根据对截止时间的要求不同分类

  • 硬实时任务:指系统必须满足任务对截止时间的要求,否则后果要命。
  • 软实时任务:任务与预期的截止时间相关联,但不是绝对严格。

根据任务执行是否呈现周期性来分类

  • 周期性任务:以固定的时间间隔出现的事件,如每周期T出现一次。
  • 非周期性任务:事件的出现无法预计,但规定了必须完成或开始的时间。

实时调度算法

  • 静态调度:在系统开始运行之前做出调度决策。
  • 动态调度:在运行时做出调度决策。

实时调度算法

优先级随速率单调算法(Rate Monotonic Scheduling, RMS)

调度策略

  • 该算法为每个进程分配一个固定的优先级,等于触发事件发生的频度。
  • 比如,一个进程每30ms必须运行一次,每秒运行33次,优先级为33;每40ms运行一次,每秒运行25次,优先级为25。进程的优先级与其速率是线性关系。
  • 任务周期最短的进程优先级最高,调度程序总是运行优先级最高的进程,必要时抢占。
  • 一句话:先调运行速率快的

举例:

例:系统有3个进程ABC

  • A,每30ms必须运行一次(优先级是33)
  • B,每40ms必须运行一次(优先级是25)
  • C,每50ms必须运行一次(优先级是20)
  • A、B、C每次的运行时间分别是10ms、15ms、5ms
  • 开始时3个进程都就绪

调度过程

image-20221006084647214

最早截止时间优先调度算法(Earliest Deadline First, EDF)

调度策略

  • 该算法为每个进程分配一个固定的优先级,等于触发事件发生的频度。
  • 比如,一个进程每30ms必须运行一次,每秒运行33次,优先级为33;每40ms运行一次,每秒运行25次,优先级为25。进程的优先级与其速率是线性关系。
  • 任务周期最短的进程优先级最高,调度程序总是运行优先级最高的进程,必要时抢占。
  • 一句话:先调截止时间早的(按周期)

image-20221006085356447

4.8 多处理器调度

用的都是简单的调度算法

多处理器系统与单处理器系统相比,在速度、性能、可靠性等方面有很大提高,但结构和管理也变得更复杂。

多处理器系统主要分为三种类型:

  • 松散耦合多处理器系统(集群系统)
  • 紧密耦合多处理器系统
  • 主从多处理器系统

与单处理机调度的区别

  • 注重整体运行效率(而不是个别处理机的利用率)
  • 具有更多样的调度算法
  • 调度单位广泛采用线程

与多处理器调度相关的主要内容:

  • 给处理器分配进程
    • 静态分配:把一个进程固定地分给一个处理器,每个处理器只保持一个就绪队列。调度开销小,但各处理器可能忙闲不均。
    • 动态分配:把系统中所有就绪进程放入一个全局队列,从中选出进程分派到任何可用的处理器上。一个进程在其生命周期内可能在不同时间、不同处理器上执行。
  • 在单个处理器上使用多道程序技术
    • 传统的多处理器中没有线程,每个处理器在若干进程之间切换,可获得高利用率和良好性能。
    • 如果一个应用程序由多线程的单个进程实现,则让组成一个应用程序的所有线程同时运行,性能最好
  • 实际分派进程或线程(采用调度算法)
    • 调度算法越简单,开销越小,效率就越高。
    • 一般采用先来先服务和静态优先级算法。

多处理器中线程调度的方式

  • 负载共享

    系统维护一个全局就绪线程队列,当某个处理器空闲时,就从该队列中选择一个线程。

  • 成组调度

    把一组相关线程作为一个单位同时调到一组处理器上运行,所有线程一起开始和结束它们的时间片。

  • 专用处理器分配

    当一个进程被调度时,它的每个线程被分配到一个处理器上,在该进程完成之前,处理器由相应的线程专用。

  • 动态调度

    允许在进程执行期间动态改变其线程的数目。

UNIX/Linux进程调度

UNIX进程调度

  • 一般策略:抢占式优先级
  • 实现思想
    • 系统为每个进程都计算一个优先级,核心从就绪队列中挑选一个优先级最高的进程,为其分配一个时间片,使其运行。
    • 在运行过程中,当前进程的优先级随时间递减,实现负反馈,即经过一段时间后,原来级别较低的进程就相对“提升”了级别。
    • 当所有进程的优先级都变为最低时,就重新计算一次所有进程的优先级。

Linux进程调度

中断处理

信号机制

第五章:存储器管理

用户程序的地址空间

程序必须装入到内存才能运行。也就是说,创建活动进程的第一步就是把程序装入内存并建立进程的映像。装入程序根据内存的使用情况和分配策略,将上述装入模块放入分配到的内存区中。这时可能需要进行重定位。用户程序经编译之后的每个目标模块都以О为基地址顺序编址,这种地址称为相对地址或逻辑地址内存中各物理存储单元的地址是从统一的基地址开始顺序编址的,这种地址称为绝对地址或物理地址。所以程序的逻辑地址与物理地址是不同的概念。

通常,程序装入内存的方式有以下三种:

  1. 绝对装入方式。将装入模块存放到内存的指定位置中,装入模块中的地址始终与其内存中的地址相同。即在装入模块中出现的所有地址都是内存的绝对地址。
  2. 可重定位装入方式。由装入程序根据内存当时的使用情况,决定将装入模块放在内存的什么地方。装入模块内使用的地址都是相对地址。
  3. 动态运行时装入方式。为使内存利用率最大,装入内存的程序可以换出到磁盘上,以后再换入到内存中,但对换前后在内存中的位置可能不同。也就是说,允许进程的内存映像在不同时候处于不同的位置。

重定位

由程序中逻辑地址组成的地址范围叫做逻辑地址空间,或简称为地址空间;由内存中一系列存储单元所限定的地址范围称作内存空间,也称物理空间或绝对空间。

重定位:程序和数据装入内存时,需对目标程序中的地址进行修改。这种把逻辑地址转变为内存物理地址的过程称作重定位。

静态重定位

静态重定位是在目标程序装入内存时,由装入程序对目标程序中的指令和数据的地址进行修改,即把程序的逻辑地址都改成实际的内存地址。对每个程序来说,这种地址变换只是在装入时一次完成,在程序运行期间不再进行重定位。按照静态重定位方式,图5-3所示的程序A装入内存时的情况变成图5-4所示的样子。

image-20221011090143040

静态重定位的优点

  • 无需增加硬件地址转换机构
  • 便于实现程序的静态连接
  • 在早期计算机系统中大多采用这种方案

主要缺点

  • 程序的存储空间只能是连续的一片区域,而且在重定位之后就不能再移动,这不利于内存空间的有效使用。
  • 各个用户进程很难共享内存中的同一程序的副本。

动态重定位

动态重定位是在程序执行期间,每次访问内存之前进行重定位。(当调度该进程在CPU上执行时,才进行相关地址的重定位。)

动态重定位经常用硬件实现。所需的硬件支持包括一对寄存器:一个存放用户程序在内存的起始地址,称作基址寄存器;另一个存放用户程序逻辑地址的最大范围,称作限长寄存器。例如,某进程(进程3)装入内存的起始地址是64K,其大小是24 KB。当进程3执行时,操作系统自动将该进程在内存的起始地址(64 K)放入基址寄存器中,把其大小(24 KB)放入限长寄存器中。动态重定位的实现过程如图

image-20221011090518724

当执行LOAD 1,3000这条指令时(即把相对地址为3000的单元中的数据123取到1号寄存器),操作对象的相对地址(3000)首先与限长寄存器的值(24KB)进行比较:如果前者小于后者,则表示地址合法,在限定范围之内。接着,将相对地址与基址寄存器中的地址相加,所得结果就是真正访问内存的地址;如果前者不小于后者,则表示地址越界,发出相应中断,进行处理。

如果用(BR)表示基址寄存器的内容,用addr表示操作对象的相对地址,则操作对象的绝对地址就是(BR) +addr的值。通常,系统中有很多用户进程,但是基址/限长寄存器只有一对。它们是专用的特权寄存器,只能由操作系统设置它们的值。每当选中一个进程运行时,就要为它设置这对寄存器的值。

动态重定位的主要优点

  • 程序占用的内存空间动态可变,不必连续存放在一处。
  • 比较容易实现几个进程对同一程序副本的共享使用。

它的主要缺点

  • 需要附加硬件支持,增加了机器成本,
  • 而且实现存储管理的软件算法比较复杂。

与静态重定位相比,动态重定位的优点是很突出的。所以,现在的计算机系统中都采用动态重定位方法。

分区法

分区分配是为支持多道程序运行而设计的一种最简单的存储管理方式。在这种方式下,除操作系统占用内存的某个固定分区(通常是低址部分)外,把其余内存供用户程序使用,并且划分成若干分区,每个分区里容纳一个作业。按照分区的划分方式,可分为固定分区法和动态分区法两种常见的分配方法。

固定分区法

固定分区就是内存中分区的个数固定不变,各个分区的大小也固定不变,但不同分区的大小可以不同。每个分区只可装入一个进程。

划分分区大小有两种方式:一种是**等分方式,即各分区都有同样大小;另一种是差分方式**,即不同分区有不同大小。等分方式有明显的缺点,如浪费大,可能无法装入大程序等。所以,实际运行的系统大多采用差分方式,即有些分区容量较小,适于存放小程序;有些分区容量较大,适于存放大程序。

image-20221011091133459

固定分区法管理方式简单,所需操作系统软件和处理开销都小。它的缺点是:

  • 内存空间利用率不高,有时浪费情况会相当严重,即存在碎片问题。如在图5-8所示的情况下,进程4提出内存申请:需要10KB空间。系统可以满足其要求:将分区4分给它。这样一来,分区4就有60KB的空间白白浪费了。因为进程4占用这个分区后,不管剩余多大空间,都不能再分给别的进程使用。
  • 要在系统生成时指定分区的个数,这就限制了系统中处于活动(不是阻塞的)状态的进程数目;另外,在多数情况下,并不能预先知道所有作业对内存的需求,而分区大小是在系统生成时确定的。

动态分区法

由于用户进程的大小不可能预先规定,而且进程到来的分布情况也无法预先确定,所以固定分区法中分区的大小不会总与进程大小相符。为了解决内存浪费问题,可把分区的大小和个数设计成可变的。就是说,各个分区是在相应进程要进入内存时才建立的,使其大小恰好适应进程的大小。这种技术称为动态分区法

在采用动态分区法的系统中,操作系统内部设置一个内存登记表,记载整个内存中所有空闲区和已用区的情况,每个分区占一个表项,每个表项包括相应分区的大小、位置和状态等。最初,除操作系统占用的分区外,全部内存对用户进程都是可用的,可视为一大块。当某个进程(设其大小为50KB)需要装入内存时,系统就从该表的开头依次搜索各表项,从中找一个足以放下这个进程的空闲区:如果该分区的大小恰好也是50KB,则把该区分给这个进程使用,并且在其表项中做上“已用”标记;如果这个空闲区比进程需要的还大,如为70KB,于是该分区一分为二,一部分(50KB)是该进程要用的,另一部分是剩下的较小空闲区(20KB),为此要建立一个新表项,登记这个较小空闲分区。当某个进程终止后,应释放其所占分区,并在相应表项中做上“空闲”标记。另外,如果新释放的分区恰好与其他空闲区相邻接,则系统还要将它们合并起来,使之成为一个连续的更大的空闲区,当然,相应的表项要归并。

image-20221011091531388

数据结构

为了实现分区分配,系统要设置相应的数据结构来记录内存的使用情况。常用的数据结构形式有以下两种。

(1)空闲分区表
空闲分区表的格式示意如图5-11所示。内存中每个空闲的分区占用该表的一项,每个表项的内容包括:分区号、分区大小、分区起始地址及该分区的状态等。当分配内存空间时就查表,如果找到满足要求的空闲分区,则实施分配。

image-20221011091705103

(2)空闲分区链
空闲分区链是使用链指针把所有的空闲分区链接成一条链。为此,在每个分区的开头要设置状态位和表示分区大小的项目,状态位标示该分区是否已分配出去;还要设置前向指针,用来链接前面一个分区;在每个分区的尾部要设置一个后向指针,用来链接后面一个分区。分区的中间部分是可以存放进程的空闲内存空间。当该分区分配出去后,就把状态位由“0”(空闲)改为“1”(已用)。

分配算法

当把一个进程装入内存或者换入内存时,若有多个容量满足要求的空闲内存区,操作系统必须决定分配哪个分区。从一组空闲区中选择一个可用区的策略有三种:最先适应算法(First-fit).最佳适应算法(Best-fit)和循环适应算法(Next-fit)。

最先适应算法(First-fit)

在这种算法中,空闲表是按地址排列的,即空闲分区起始地址小的分区在表中的序号也小。当要为进程分配内存空间时,就**从该表的开头向下查,在各空闲分区中查找满足大小要求的可用分区。**只要找到第一个足以满足要求的空闲分区就停止查找,并把它分配出去;如果该空闲分区与所需内存的大小一样,则从空闲表中取消该项;如果该空闲分区大于所需内存,那么分出所需内存空间后还有剩余,则余下的部分仍留在空闲表中,但应修改分区大小和分区始址。

这种算法的优点是:便于释放内存时进行合并,且为大进程预留高地址部分的大空闲区。

缺点是:内存高地址部分和低地址部分的利用不均衡,且会出现许多很小的空闲分区,影响内存效率。

最佳适应算法(Best-fit)

这种算法的空闲表是以空闲分区的大小为序、按增量形式排列的,即小分区在前,大分区在后。它在满足需要的前提下,尽量分配最小的空闲分区。
这种算法产生的剩余空闲分区是最小的,但它不便于释放内存时与邻接空闲分区的合并,也同样会出现许多难以利用的小空闲分区。

循环适应算法(Next-fit)

这种算法是最先适应算法的变种。它不从空闲表的开头查找,而从上次找到的可用分区的下一个空闲分区开始查找,从中选择满足大小要求的第一个空闲分区。
该算法能使内存中的空闲分区分布得更均匀,减少查找空闲分区的开销。在实现时设置一个指针,用于指示下一次搜索的起始位置。它无法为大作业预留大的空闲分区。

可重定位分区分配

碎片问题

在固定分区法和动态分区法中,必须把一个系统程序或用户程序装入一个连续的内存空间中。虽然动态分区法比固定分区法的内存利用率高,但由于各个进程申请和释放内存的结果,在内存中经常出现大量的分散的小空闲区

大量碎片的出现不仅限制了内存中进程的个数,还造成了内存空间的大量浪费。怎样使这些分散的、较小的空闲区得到合理使用呢?

最简单的办法是定时或在分配内存时把所有碎片合并为一个连续区,如图5-13所示。实现的方法是**移动某些已分配区的内容,使所有进程的分区紧挨在一起,而把空闲区留在另一端。**这种技术称为紧缩(或拼凑)。采用紧缩技术的动态分区法也称为可重定位分区法。

由于紧缩过程中内存中的进程要“搬家”,因而所有对地址敏感的项都必须做适当修改,如基址寄存器、访问内存的指令、参数表和使用地址指针的数据结构等,采用动态重定位技术可以较好地解决这个问题。
利用紧缩法消除碎片,需要对分区中的大量信息进行传送,这要花费大量的CPU时间。为了减少进程移动的数量,可对紧缩方向加以改进。进程装入内存时,不是从上至下依次放置,而是采用“占两头,空中间”的办法。当紧缩时,各个进程按地址大小分别向两端靠拢,从而使空闲区保留在内存的中间部位。

image-20221011092153787

何时紧缩?两种方案

第1种方案是当进程结束、释放所占用的分区时,如果它不与空闲区邻接,就立即进行紧缩。于是,空闲区总是保持连续的一片空间,不会出现分散的碎片。这样,对空闲区的管理和为进程分配内存分区就很容易。但是紧缩却花费很多时间。

第2种方案是在分配进程的分区时进行,即各个空闲区都不能满足该进程的需求时才进行紧缩。也就是说,回收分区时不进行紧缩,存在足够大的空闲区时也不做紧缩。这样,紧缩的次数就比第1种方案少得多。但空闲区的管理较前者复杂。

优缺点

可重定位分区分配技术的优点是可以消除碎片,能够分配更多的分区,有助于多道程序设计,提高内存的利用率。它的缺点是:为消除碎片,紧缩花费了大量CPU时间,从而降低了处理器的效率;当进程大于整个空闲区时,仍要浪费一定的内存;进程的存储区内可能放有从未使用的信息:进程之间无法对信息共享。

分页技术

5.4.1 分页技术的引入

分页技术:允许一个进程的存储空间不必连续,可以分散地放在各个空闲的内存区域中。解决了外部碎片,并提高了内存的利用率

5.4.2 分页存储管理的基本概念

(1)逻辑空间分页
(2)内存空间分块
(3)内存分配原则
(4)页表
(5)内存块表
(6)逻辑地址表示

5.4.3 分页系统中的地址映射

5.4.4 页面尺寸

5.4.5 硬件支持

5.4.6 保护方式

5.4.7 页表的构造

5.4.8 页面共享

分段技术

页面置换算法

最佳置换法(OPT)

思想:为调入新页面而必须预先淘汰某个老页面时,所选择的老页面应在将来不被使用,或者是在最远的将来才被访问。以此保证获得最低的缺页率。

image-20221025141953198

优点:
性能最佳,缺页中断率最低。
缺点:
理想化的算法,无法实现。
因为它需要预先知道一个进程整个运行过程中页面走向的全部情况。
作用:
模拟实验分析或理论分析其他算法的优劣。

先进先出法(FIFO)

**思想:**为调入新页面而必须预先淘汰某个老页面时,总是淘汰在内存中停留时间最长的一页,即先进入内存的页,先被换出

实现方法

  1. 计时器。在页面上加计时器记录最早进入的页。
  2. 队列。只需把调入内存的页面根据先后次序链接成队列,设置一个指针总是指向队首的页面。

image-20221025142125250

优点:
容易理解,实现简单,方便程序设计。
缺点:
性能不好。因为常被访问的页,通常在内存中停留最久。
仅当按线性顺序访问地址空间时,才是最理想的,否则效率不高。
作用:
作为基础算法被应用在其他算法中。

最近最少使用置换法(LRU)

**Least Recently Used。**也称“最近最久未使用置换法”。
**思想:**当需要置换一页时,选择在最近一段时间里最久没有使用过的页面予以淘汰。
**理由:**认为过去一段时间内未被访问过的页面,在最近的将来可能也不会被访问。

实现方法
1、计数器。
要求在硬件上有一个64位的计数器C(给CPU增加一个计数器C),每条指令执行完后,C的值自动加1 。
在每个页表项中,增加一个“使用时间”字段(时间戳)。每一次内存访问后,C的值就被复制到被访问页面的“使用时间”字段中。
系统始终保留着每个页面最后被访问的“时间”,淘汰该时间值最小的页面,即最近最久未被使用的页面。

2、栈。

用一个栈保留页号,每访问一个页面时,就把它从栈中取出,放入栈顶。要用具有首指针和尾指针的双向链把各个栈单元连起来。

image-20221025143412747

image-20221025142952365

第二次机会置换法(SCR)

SCR是对FIFO算法的改进—— 避免把经常使用的页面置换出去。
基本思想:当选择某一页面置换时,就检查最老页面的引用位R:如果是0,就立即淘汰该页;如果是1,就给它一次机会。将引用位清0,并把它放入页面链表的末尾,把它的装入时间置为当前时间;然后选择下一个FIFO页面。

image-20221025144617921

  • 页面A~H按进入内存时间的先后为序排列在链表中。最早进入的是A。设在时刻20出现缺页。
  • 若A的引用位为1,则把它放入链尾,其引用位清0,从B开始寻找置换页。
  • 如果所有页面的引用位都是1,则算法退化为FIFO。扫面一遍所有页面,同时将引用位都清0。又回到A,淘汰A。同时看A的修改位,如果是1, 则写回磁盘,否则简单放弃。

简单时钟置换法(NRU)

SCR算法需要页面在链表中移动,带来效率降低的问题。
改进办法:把所有页面保存在一个类似钟表表盘的环状链表中,由一个指针指向最老的页面。
Clock算法是对SCR的改进,也是对LRU算法的近似。

基本思想:

当缺页时,检查指针指向的页面,若它的引用位为0就淘汰它,把新页面插入这个位置,指针下移;

若引用位为1,则将其清0,指针下移,直至找到引用位为0的页面为止

image-20221025144705268

改进时钟置换法

在选择淘汰页面时,同时看引用位和修改位。
当启动一个进程时,它的所有页面的引用位和修改位设置为00。
引用位在每次时钟中断时清零,以区别最近没有被访问的页面和被访问的页面。
修改位在页面被修改过后置1,并不被时钟中断修改。

当发生缺页时,OS检查所有的页面并根据它们当前的引用位和修改位的值,将页面分为4种情况:

0类:00,最近未访问,没有被修改

1类:01,最近未访问,已被修改

2类:10,最近被访问,没被修改

3类:11,最近被访问,已被修改
内存中的每个页面必定是上述四类中的一类。

从指针所指示的当前位置开始, 扫描循环队列, 将所遇到的第一个第0类页面作为所选中的淘汰页。 在第一次扫描期间不改变引用位。
如果查找一周后未遇到第0类页面, 则开始第二轮扫描,寻找第1类页面,将所遇到的第一个这类页面作为淘汰页。在第二轮扫描期间,将所有扫描过的页面的引用位都置0。
如果也未找到第1类页面,则将指针返回到开始的位置,并将所有的引用位复0。 然后重复第一步,如果仍失败,必要时再重复第二步,此时就一定能找到被淘汰的页。

最少使用算法(NFU)

Least Frequently Used
LRU算法的软件模拟
基本思想:选择到当前时间为止被访问次数最少的页面置换。
实现方法:
为每页设置一个软件计数器,用于记载该页被访问的次数,其初值为0。
在每次时钟中断时,操作系统扫描内存中的页面,将每页的引用位R的值加到对应的计数器上。这个计数器可粗略反映各页被访问的频繁程度。
发生缺页时,淘汰计数值最小的页面。

存在的问题:某些页面在进程刚开始时频繁使用,而后不再使用,但其计数器的值一直保持很大,因而操作系统可能会淘汰有用的页面。
对LFU做一个小小的修改,使其更好地模拟LRU。
先把计数器的值右移一位,然后再把R的值加进来;
把R的值插入到计数器的最左端而不是最右端。
修改后的算法称为老化算法。

image-20221025150232841

当发生缺页中断时,计数器值最小的页面被淘汰。

如果一个页面连续2个时钟节拍未被访问过,则它的计数器最左边有2个0。

老化算法与LRU算法有两点区别:1. 在一个时钟周期内无法区分两个页面的访问顺序,因为一个周期只记录一位。

老化算法与LRU算法有两点区别:2.老化算法的计数器只有有限位,本例中是8位。如果两个页面的计数器都是0,只能随机选一个。而可能一个页面的上次访问时间是9个节拍前,另一个是1000个节拍以前。

页面缓冲算法(Page Buffering)

对FIFO算法的改进,通过对被置换页面的缓冲,有机会找回刚被访问的页面。
该算法维护两个链表:
空闲页链表:即页面内存块链表,直接用于读入页面;
修改页链表:由已修改页面的内存块构成的链表。

基本思想:当发生缺页时,按照FIFO算法选取一个老页面,不是抛弃它,而是把它放入两个链表之一。
如果该页未被修改,就放入空闲页链表的末尾;否则把它放入修改页链表的末尾。
页面在内存中不做物理移动,只是把页表中的表项链入上述两个链表之一。
需要读入的页面,装入空闲页链表中的第一个内存块,使得该进程尽可能快地重新启动。不必等到淘汰页面被写出去。

空闲页面和已修改页面,仍停留在内存中一段时间,如果这些页面被再次访问,只需较小开销,就使它回到该进程的驻留集(进程在内存映像的集合)中。
当修改页链表中的页数达到一定数目后,就把它们一起写回磁盘,再把它们放入空闲页链表,这样能大大减少I/O操作的次数和磁盘存取时间

工作集页面置换算法

工作集:就是一个进程在某一小段时间内访问页面的集合。
工作集举例:如用WS(ti)表示在ti-△到ti之间所访问的不同页面,那么它就是进程在时间ti的工作集。

image-20221025152552509

分页系统设法跟踪进程的工作集,以确保让进程运行以前,它的工作集就已在内存中。该方法为工作集模型。目的在于减少页面失效率。分页系统设法跟踪进程的工作集,以确保让进程运行以前,它的工作集就已在内存中。该方法为工作集模型。目的在于减少页面失效率。

基本思想:找出一个不在工作集中的页面并淘汰之。

期末要考

image-20221025144032335

image-20221025144044109

image-20221025144058191

image-20221025144106903

内存块的分配与抖动问题

内存块的分配

内存块的分配算法
等分法
比例法
优先权法

image-20221025154019462

内存块的分配策略

固定分配策略:分配给进程的内存块数是固定的,且在最初装入时(即进程创建时)确定块数。
可变分配策略:允许分给进程的内存块数随进程的活动而改变

页面置换范围

全局置换:允许一个进程从全体存储块的集合中选取页面淘汰,尽管该块当前分配给其他进程,还是能强行占用。
局部置换:是每个进程只能从分给它的一组内存块中选择页面淘汰

内存块的分配策略+页面置换范围

固定分配+局部置换
主要问题:进程开始前要依据进程类型决定分配多少内存块。多了会影响并发水平,少了会使缺页率过高。
可变分配+局部置换
局部置换,但在大尺度上进行可变分配。
可变分配+全局置换
主要问题:置换策略的选择,选择哪个进程的页面被调出,较好的选择是页面缓冲算法。
不包括“固定分配+全局置换”

抖动问题

抖动:在虚存中,页面在内存与外存之间频繁调度,以至于调度页面所需时间比进程实际运行的时间还多,此时系统效率急剧下降,甚至导致系统崩溃。这种现象为“抖动或颠簸(Thrashing)” 。

产生抖动的原因
页面淘汰算法不合理
分配给进程的内存块数太少

防止抖动的方法

  1. 采用局部置换策略
    一个进程出现抖动,它不能从其他进程那里获取内存块,不会引发其他进程出现抖动,使抖动局限于一个小范围内。
  2. 利用工作集策略防止抖动
  3. 挂起某些进程
    当出现CPU利用率很低、而磁盘I/O非常繁忙时,可能因为多道程序度太高而造成抖动。挂起一个或几个进程,腾出内存空间供抖动进程使用。
  4. 采用缺页频度法(Page Fault Frequency, PFF)
    抖动发生时缺页率会很高,通过控制缺页率可防止抖动。

image-20221025154203382

请求分段技术

在段式虚存系统中,一个进程的所有分段的副本都保存在外存上。当它运行时,先把当前运行的一段或几段装入内存,其他段仅在调用时才装入。

第六章:文件系统

6.1 概述

6.1.1文件分类

按文件的内部构造和处理方式分类

  • 普通文件 由ASCII码或二进制码组成的字符文件。

    包括:源程序文件、数据文件、目标代码文件、系统文件、库文件等。一般存放在外存上。

  • 特别文件 特指各种外部设备

    把设备当做文件来看待

    • 特别文件分为字符特别文件和块特别文件。
    • 字符特别文件是有关输入输出的设备,如终端、打印机等;
    • 块特别文件是存储信息的设备,如硬盘、软盘和磁带等。
  • 目录文件

    由下属文件的目录项构成的,用来管理和实现文件系统功能的系统文件,通过目录文件可以对其他文件的信息进行检索。

    目录文件类似于人事管理方面的花名册,本身不记录个人的档案信息,仅仅列出姓名和档案分类编号。

6.1.2 文件的逻辑结构

从逻辑结构上看,文件可分为有结构的记录式文件无结构的流式文件两种形式。

无结构文件
  • 指文件内部不再划分记录,是由一组相关信息组成的有序字符流。又称流式文件。
  • 长度按字节计算。大量源程序、可执行程序、库函数都是流式文件。
  • 在UNIX系统中所有文件都被视为流式文件,系统不对文件进行格式处理。
有结构文件
  • 文件是由若干相关记录组成,且对每个记录编上号码。又称记录式文件。
  • 数据库文件就是有结构文件。
    • 定长记录文件
    • 变长记录文件
  • 树形文件是一种有结构的文件。

6.1.3 文件的物理结构

物理结构主要依赖于文件存储器(磁带、磁盘、光盘等)的物理特性及用户对文件的访问方式。

  • **顺序存取:**基于磁带的存取模式。读操作按照文件指针指示的位置读取文件内容,文件指针自动向前推进。写操作把信息附加到文件的末尾。
  • **随机存取:**基于磁盘的存取模式。允许以任意顺序读取文件,主要用于对大批数据的立即访问。
  • **索引存取:**建立在随机存取之上。
顺序结构
  • 逻辑文件在辅存上连续存储,其物理结构即为顺序结构。
  • 顺序结构适合对文件的顺序访问。
  • 对文件执行增补或删除只能在文件末端进行
链接结构

文件在辅存中是散布在非连续的若干物理块中的,用向前指针把每个记录依次链接起来。
空间利用率高,文件操作(增加、删除)灵活。

索引结构

文件的全部逻辑记录散存于辅存的各物理块中,为文件建立一张索引表,存放逻辑记录编号、长度、在辅存的位置。

6.2 文件系统的功能和结构

6.2.1 文件系统的功能

就是操作系统中负责操纵和管理文件的一整套设施

文件系统应具备以下功能

文件管理
目录管理
文件存储空间管理
文件的共享和保护
提供方便的接口

6.2.2 文件系统的结构

文件系统的层次结构

逻辑文件系统

最上层是逻辑文件系统,它管理元数据信息。

  • 元数据包括除实际数据(文件内容)以外的所有文件系统结构。
  • 创建文件控制块。
  • 管理目录结构。
  • 实现按名存取。
  • 负责文件的保护和安全。
  • 提供文件组织模块需要的信息。

文件组织模块

文件组织模块把文件的逻辑块地址转换成物理块地址,传送给基本文件系统。负责管理空闲盘空间,记载文件系统中未分配的盘块。

基本文件系统

基本文件系统只需向相应的设备驱动程序发出通用命令,令其读/写盘上的物理块。

IO控制

包括设备驱动程序和中断处理程序,实现内存和磁盘系统之间的信息传送。接收高级命令,输出低层的硬件专用指令,传送给控制器使用。

6.3文件控制块和文件目录

文件控制块

  • 为了便于对文件进行控制和管理,在文件系统内部,给每个文件唯一地设置一个文件控制块。
  • 文件控制块存储:文件名、文件类型、大小、属性、保护信息、位置、使用计数、时间
  • 核心利用这种结构对文件实施各种管理。按名存取时,先找到文件控制块,验证权限,合法时才能取得存放文件信息的盘块地址。

MS-DOS系统

  • 在MS-DOS系统中,一个目录项有32字节长,利用首块号作为查找物理块链接表的索引,按索引链向下查找,可以找到该文件的所有盘块。
  • 一个目录中可以包含其他目录,从而形成层次结构的文件系统。

UNIX系统

  • UNIX系统的目录项只由文件名和I节点号组成。
  • 有关文件的具体信息都存放在I节点中。
  • 由文件名找到对应的I节点号,再从I节点中找到文件的控制信息和盘块号。

文件目录

  • 为了加快对文件的检索,往往将文件控制块集中在一起进行管理。这种文件控制块的有序集合称为文件目录。
  • 完全由目录项构成的文件称为目录文件。

区分文件目录和目录文件

目录操作

  • 查找
  • 建立文件:建立新文件,把文件控制块加到目录中。
  • 删除文件:当文件不需要时,从目录中抹掉它。
  • 列出目录清单:显示目录内容和该清单中每个文件目录项的值。
  • 后备:定期把全部文件复制到新磁盘上。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值