|
|
*written by PeterAlbus,Copyright © 2021 - SHOU 1951123 Hong Wu*
|
|
|
|
|
|
**注:对于2021年上海海洋大学期末考试来说,打\*的部分不在韩彦岭老师提供的期末复习提纲中(若一个根目录标识了\*号,则所有子目录也不在复习提纲中),但阅读或许有助于加深对操作系统整体的理解。此外,有些部分课本与上课教学顺序并不一致,考虑到课堂教授顺序更符合理解顺序,某些部分可能会重新编号,与课本顺序不同。**
|
|
|
|
|
|
---
|
|
|
|
|
|
# 第一章 操作系统概论
|
|
|
|
|
|
> **操作系统**(operation system, OS)是配置在计算机硬件平台上的第一层软件,是管理整个计算机软硬件资源的系统软件。
|
|
|
|
|
|
### 1.1 操作系统的概念
|
|
|
|
|
|
操作系统是计算机系统中一组控制和管理计算机硬件资源和软件资源,合理地对各类作业进行调度,以方便用户使用的程序的集合。
|
|
|
|
|
|
操作系统的主要功能(五大功能):
|
|
|
|
|
|
+ 处理器管理
|
|
|
+ 存储器管理
|
|
|
+ 设备管理
|
|
|
+ 文件系统
|
|
|
+ 用户接口
|
|
|
|
|
|
### 1.2 操作系统的发展历程
|
|
|
|
|
|
> 无操作系统时代→单道批处理系统→多道程序系统→分时操作系统→实时操作系统
|
|
|
|
|
|
#### 1.2.1 无操作系统时代(1945-1955)*
|
|
|
|
|
|
程序员采用纸带或卡片记录程序,人工操作,人工I/O。计算机运行速度提高后会导致I/O速度和计算速度极其不匹配。
|
|
|
|
|
|
缺点:
|
|
|
|
|
|
+ 用户独占资源
|
|
|
+ 人工干预较多
|
|
|
+ CPU等待人工操作
|
|
|
|
|
|
#### 1.2.2 单道批处理系统(1955-1965)*
|
|
|
|
|
|
由监督程序依次将磁盘中的作业调入内存,待作业执行完毕后再把控制权交还给监督程序。
|
|
|
|
|
|
严格来说,它只能算作OS的前身而并非是现在人们理解的OS。
|
|
|
|
|
|
主要特征:
|
|
|
|
|
|
+ 自动性
|
|
|
+ 顺序性
|
|
|
+ 单道性
|
|
|
|
|
|
#### 1.3.3 多道程序系统(1965-1980)*
|
|
|
|
|
|
在该系统中,用户所提交的作业都先存放在外存上并排成一个队列,称为”后备队列“;然后,由作业调度程序按一定的算法从后备队列中选择若干个作业调入内存,使他们共享CPU和系统中的各项资源。
|
|
|
|
|
|
#### 1.2.4 分时操作系统
|
|
|
|
|
|
分时操作系统让用户通过与计算机相连接的终端来使用计算机系统,允许多个用户同时与计算机系统进行一系列交往。(举例:linux系统的计算机可以通过SSH与多个用户同时远程连接,多个用户在不同终端输入指令)系统能快速地对用户提出的请求给予应答,使得每个用户都感到好像各自有一台独立支持自己请求服务的计算机。
|
|
|
|
|
|
> 允许多个联机用户同时使用一台计算机进行计算地操作系统称**分时操作系统**(time sharing operating system)
|
|
|
|
|
|
分时操作系统的四个特点:
|
|
|
|
|
|
+ 多路性
|
|
|
+ 独立性
|
|
|
+ 及时性
|
|
|
+ 交互性
|
|
|
|
|
|
目标:公平、高效
|
|
|
|
|
|
#### 1.2.5 实时操作系统*
|
|
|
|
|
|
> **实时操作系统**(real time operating system)是指当数据或事件产生时,能够接受并以足够快的速度处理,其处理的结果又能在规定的时间内来控制生产过程或对处理系统做出快速响应,并控制所有实时任务协调一致运行的操作系。
|
|
|
>
|
|
|
> 提供及时响应和高可靠性是其特点。
|
|
|
|
|
|
特点:
|
|
|
|
|
|
+ 多路性
|
|
|
+ 独立性
|
|
|
+ 及时性
|
|
|
+ 交互性
|
|
|
+ 可靠性
|
|
|
|
|
|
#### 1.2.6 各种操作系统类型极其简介
|
|
|
|
|
|
+ 微机操作系统:文件管理,执行程序
|
|
|
+ 网络操作系统:具备网络接口的传统操作系统
|
|
|
+ 分布式操作系统:用于管理分布式计算机系统的操作系统
|
|
|
+ 嵌入式操作系统:在计算机硬件网络上配备的支持应用软件的系统软件是嵌入式操作系统
|
|
|
|
|
|
### 1.3 操作系统的基本特征
|
|
|
|
|
|
并发性、共享型、虚拟性、异步性。
|
|
|
|
|
|
并发性是操作系统最重要的特性。
|
|
|
|
|
|
并发性和共享型是操作系统最基本的特征。
|
|
|
|
|
|
#### 1.3.1 并发性
|
|
|
|
|
|
> **并发性**(concurrence)是指两个或两个以上的事件或活动在同一时间间隔内发生。
|
|
|
>
|
|
|
> (并行:两个/多个事件在同一时刻内发生)。
|
|
|
|
|
|
操作系统引入了进程来解决并发问题。
|
|
|
|
|
|
#### 1.3.2 共享性
|
|
|
|
|
|
> **共享**是指操作系统中的资源(包括硬件资源和软件资源)可被多个并发执行的进程共同使用,而不是被一个进程独占。
|
|
|
|
|
|
资源共享的方式:
|
|
|
|
|
|
+ 互斥访问:一段时间只允许一个进程访问。这样的资源被称为临界资源。
|
|
|
+ 同时访问:同一时间段允许多个进程访问。典型的此类资源:硬盘。
|
|
|
|
|
|
#### 1.3.3 虚拟性
|
|
|
|
|
|
> **虚拟性**是指擦奥做系统中的一种管理技术,它把物理上的一个实体编程逻辑上的多个对应物,或者把物理上的多个实体变成逻辑上的一个对应物的技术。
|
|
|
|
|
|
Spooling技术、窗口技术、虚拟存储器......
|
|
|
|
|
|
#### 1.3.4 异步性
|
|
|
|
|
|
> **异步性**也称随机性,是指多道程序环境中多个进程的执行、推进和完成时间都是随机的、交替的不可预测的。
|
|
|
|
|
|
操作系统需要考虑一部性问题使结果一致。
|
|
|
|
|
|
### 1.4 操作系统的功能
|
|
|
|
|
|
五大功能(同1.1):处理器管理。存储器管理。设备管理。文件系统、用户接口
|
|
|
|
|
|
+ 处理器管理:引入了进程(线程)的概念,对处理机的管理可归结为对进程/线程的管理。
|
|
|
+ 进程控制
|
|
|
+ 进程同步
|
|
|
+ 进程通信
|
|
|
+ 调度
|
|
|
+ 作业调度:从后备队列中挑选作业分配资源,建立进程,放入就绪队列
|
|
|
+ 进程调度:从就绪队列中挑选进程分配处理机
|
|
|
+ 存储器管理:为多道程序的运行提供良好的环境,方便用户的使用,提高存储器的利用率。
|
|
|
+ 内存分配
|
|
|
+ 内存保护
|
|
|
+ 地址映射
|
|
|
+ 内存扩充
|
|
|
+ 设备管理:完成I/O请求,分配I/O设备,提高I/O速度
|
|
|
+ 缓冲管理
|
|
|
+ 数据分配
|
|
|
+ 设备处理
|
|
|
+ 文件管理:对用户文件和系统文件进行管理,方便用户使用,保证文件的安全性
|
|
|
+ 文件存储空间的管理:分配外存空间
|
|
|
+ 目录管理
|
|
|
+ 文件的读写管理和保护
|
|
|
+ 用户接口
|
|
|
+ 命令接口(由一组”命令集“组成)、图形接口
|
|
|
+ 程序接口(系统调用/高级语言库函数)
|
|
|
|
|
|
### 1.5 操作系统的结构设计*
|
|
|
|
|
|
#### 1.5.1 传统的操作系统结构
|
|
|
|
|
|
+ 无结构操作系统:逻辑复杂,维护困难
|
|
|
+ 模块化操作系统:通过分解、模块化控制大型如那件复杂度
|
|
|
+ 分层式操作系统:有序地分层
|
|
|
+ 自底向上建立若干中间层
|
|
|
+ 可简化设计的复杂度
|
|
|
+ 下层为上层提供服务
|
|
|
|
|
|
#### 1.5.2 客户、服务机模式
|
|
|
|
|
|
#### 1.5.3 微内核操作系统
|
|
|
|
|
|
+ 足够小的内核
|
|
|
+ 基于客户/服务器模式
|
|
|
+ 机制与策略分离
|
|
|
+ 采用面向对象技术
|
|
|
|
|
|
---
|
|
|
|
|
|
# 第二章 操作系统接口*
|
|
|
|
|
|
操作系统(OS)向用户提供了以下两类接口
|
|
|
|
|
|
+ 用户接口。支持用户与OS间进行交互
|
|
|
+ 程序接口,也称应用程序接口API,是为程序员在编程时使用的,系统和应用程序通过这个接口可在执行中访问系统中的资源和取得OS中的服务,它也是程序能取得操作系统服务的唯一途径。
|
|
|
|
|
|
---
|
|
|
|
|
|
# 第三章 进程管理
|
|
|
|
|
|
### 3.1 进程的基本概念
|
|
|
|
|
|
**单道程序设计**:程序的执行方式是顺序执行,即必须在一个程序执行完成后,才允许另一个程序执行。
|
|
|
|
|
|
**多道程序环境**:允许多个程序并发执行。
|
|
|
|
|
|
#### 3.1.1 程序的顺序执行及其特征
|
|
|
|
|
|
程序内部的顺序性:在处理器上的执行严格有序,即只有在前一个操作结束后,才能进行下一个操作。
|
|
|
|
|
|
程序外部的顺序性:完成一个任务若需要若干个程序,这些程序也按照调用次序严格有序执行。
|
|
|
|
|
|
特征:
|
|
|
|
|
|
+ 顺序性
|
|
|
+ 封闭性
|
|
|
+ 结果的确定性
|
|
|
+ 可再现性
|
|
|
|
|
|
#### 3.1.2 程序的并发执行及其特征
|
|
|
|
|
|
当两个操作的执行不互相依赖,则这两个这两个操作之间两个程序可并发执行。
|
|
|
|
|
|
程序的并发执行可提高系统吞吐量。
|
|
|
|
|
|
对于并发来说,宏观上似乎同一时刻在进行多个进程,实际上同一时刻仍只能进行同一进程(微观上)。
|
|
|
|
|
|
特征:
|
|
|
|
|
|
+ 间断性
|
|
|
+ 失去封闭性:多个程序共享系统中的各种资源,会使程序的运行受到其他程序的影响
|
|
|
+ 不可再现性:由于失去了封闭性,两个进程以不同的速度运行,可能出现很多不同的情况。
|
|
|
|
|
|
#### 3.1.3 进程的定义及描述
|
|
|
|
|
|
##### 1.进程的定义
|
|
|
|
|
|
> + 非正式:执行中的程序/运行中的代码段
|
|
|
> + 正式:可并发执行的程序在一个数据集合上的执行过程,是系统进行资源调度和分配的一个独立单位。
|
|
|
|
|
|
进程!=程序,程序是静态的,而进程是动态的。
|
|
|
|
|
|
##### 2.进程与程序的关系
|
|
|
|
|
|
| 进程 | 程序 |
|
|
|
| ---- | ---- |
|
|
|
| 动态 | 静态 |
|
|
|
| 并发 | 顺序 |
|
|
|
| 暂时 | 永久 |
|
|
|
|
|
|
进程与程序并非一一对应的关系。
|
|
|
|
|
|
##### 3.进程出现的动机:支持多道编程
|
|
|
|
|
|
##### 4.进程的特征
|
|
|
|
|
|
+ 结构特征:进程包含数据集合和运行于其上的程序,它至少由程序块,数据块和进程控制块等要素组成。
|
|
|
+ 动态性:进程是程序在数据集合上的一次执行**过程**。程序有其生命周期,由创建而产生,调度而执行,得不到资源而阻塞,撤销而消亡。为进程**最基本的特征**。
|
|
|
+ 并发性:没有建立PCB是不能并发执行的。(建立了进程才能并发执行)是**进程的重要特征**,也是OS的重要特征。
|
|
|
+ 独立性:进程实体是一个能独立运行,独立分配资源和独立接受调度的基本单位。
|
|
|
+ 异步性:也称随机性,是指进程按照各自独立的不可预知的速度向前推进。
|
|
|
|
|
|
### 3.2 进程状态及其转换
|
|
|
|
|
|
#### 3.2.1 进程状态及其转换
|
|
|
|
|
|
##### 1.进程的三种基本状态
|
|
|
|
|
|
+ 就绪(ready)状态:进程具备运行条件,等待系统分配处理器
|
|
|
+ 执行(running)状态:进程占有处理器正在运行
|
|
|
+ 阻塞(blocked)状态:又称为等待(wait)态或者睡眠(sleep)态。正在执行的进程由于发生某事件而无法继续执行,便放弃处理机而处于暂停状态。
|
|
|
|
|
|
![三种基本状态的转化](http://47.117.160.245:8080/pictrue/private/os_01.png)
|
|
|
|
|
|
##### 2.挂起状态(被换出内存的状态)
|
|
|
|
|
|
引入挂起状态的原因:
|
|
|
|
|
|
+ 终端用户请求
|
|
|
+ 父进程请求
|
|
|
+ 负荷调节需要
|
|
|
+ 操作系统需要
|
|
|
|
|
|
![引入挂起的状态转换](http://47.117.160.245:8080/pictrue/private/os_02.png)
|
|
|
|
|
|
#### 3.2.2 进程控制块(PCB)
|
|
|
|
|
|
进程的组成:PCB、程序段、数据段、堆栈。
|
|
|
|
|
|
引入PCB的作用:使程序成为独立运行的模块,和其他程序并发执行。
|
|
|
|
|
|
PCB是实体的一部分,是OS中最重要的数据结构。
|
|
|
|
|
|
+ PCB是进程存在的唯一标志。
|
|
|
+ PCB(Process control block)常驻内存。
|
|
|
|
|
|
##### 1.进程控制块中的信息
|
|
|
|
|
|
+ 标识信息(进程描述信息)
|
|
|
+ 进程名
|
|
|
+ 进程标识符
|
|
|
+ 用户名
|
|
|
+ 现场信息(处理机状态信息)
|
|
|
+ 通用寄存器
|
|
|
+ 指令计数器
|
|
|
+ 程序状态字寄存器
|
|
|
+ 栈指针
|
|
|
+ 进程调度信息
|
|
|
+ 进程状态
|
|
|
+ 进程优先级
|
|
|
+ 运行统计信息
|
|
|
+ 进程阻塞原因
|
|
|
+ 进程控制和资源占有信息
|
|
|
+ 进程调度信息
|
|
|
+ 进程组成信息
|
|
|
+ 族系信息
|
|
|
+ 进程间通信信息
|
|
|
+ 进程段/页表指针
|
|
|
+ CPU的占有和使用信息
|
|
|
+ 进程特权信息
|
|
|
+ 资源清单
|
|
|
|
|
|
进程控制块的组织方式:链接方式、索引方式
|
|
|
|
|
|
### 3.3 进程控制
|
|
|
|
|
|
进程管理中对进程的控制是最基本的功能。其控制包括:创建进程,终止已完成进程,状态转换。
|
|
|
|
|
|
> **原语**:计算机进程的控制通常由原语完成。所谓原语,一般是指由若干条指令组成的程序段,用来实现某个特定功能,在执行过程中不可被中断。
|
|
|
|
|
|
#### 3.3.1 进程的创建
|
|
|
|
|
|
##### 1.引起进程创建的事件:
|
|
|
|
|
|
+ 用户登录
|
|
|
+ 作业调度
|
|
|
+ 提供服务
|
|
|
+ 应用请求
|
|
|
|
|
|
##### 2.创建过程(Create原语)
|
|
|
|
|
|
+ 申请空白PCB
|
|
|
+ 为新进程分配资源
|
|
|
+ 初始化PCB
|
|
|
+ 进程描述信息
|
|
|
+ 处理机状态信息
|
|
|
+ 初始化进程控制信息
|
|
|
+ 将进程插入就绪队列
|
|
|
|
|
|
#### 3.3.2 进程的终止(原3.3.3)
|
|
|
|
|
|
##### 1.引起进程终止的事件:
|
|
|
|
|
|
+ 正常结束:HALT,logoff
|
|
|
+ 异常结束:越界、非法、I/O等
|
|
|
+ 外界干预:管理员kill等
|
|
|
|
|
|
##### 2.进程的终止过程:
|
|
|
|
|
|
+ 检查进程状态
|
|
|
+ 执行态->终止,且置调度标志位真
|
|
|
+ 检测有无子孙需终止
|
|
|
+ 归还资源给父进程或系统
|
|
|
+ PCB队列中移出被终止进程
|
|
|
|
|
|
#### 3.3.3 进程的阻塞与唤醒(原3.3.2)
|
|
|
|
|
|
##### 1.引起进程阻塞与唤醒的事件
|
|
|
|
|
|
+ 请求系统服务而得不到满足
|
|
|
+ 启动某种操作(如I/O)操作
|
|
|
+ 新的数据尚未到达
|
|
|
+ 无新工作可做
|
|
|
|
|
|
##### 2.进程阻塞过程(block原语)
|
|
|
|
|
|
是进程自身的一种主动行为
|
|
|
|
|
|
+ 停止进程执行,保存相关信息到PCB。
|
|
|
+ 修改PCB的相关内容,如修改进程状态为等待(阻塞)
|
|
|
+ 加入阻塞队列
|
|
|
+ 转入进程调度程序,调度其他进程运行
|
|
|
|
|
|
##### 3.进程唤醒过程(wake up原语)
|
|
|
|
|
|
+ 从阻塞(等待)队列取出PCB
|
|
|
+ 修改PCB的相关信息,如进程状态修改为就绪
|
|
|
+ 把修改后的PCB加入有关就绪进程队列
|
|
|
|
|
|
#### 3.3.4 进程的挂起与激活
|
|
|
|
|
|
suspend-active 原语
|
|
|
|
|
|
阻塞、唤醒一般由OS实现,而挂起、激活可以由用户实现
|
|
|
|
|
|
### 3.4 线程(原3.7)
|
|
|
|
|
|
公平和效率的权衡是进程管理永恒的话题。
|
|
|
|
|
|
进程的缺陷:
|
|
|
|
|
|
+ 一个进程在一个时间只能做一个事情
|
|
|
+ 阻塞将使进程挂起,使整个进程都无法执行
|
|
|
|
|
|
为了解决以上问题:
|
|
|
|
|
|
> 线程(threads),比进程更小的能独立运行的基本单位,
|
|
|
|
|
|
人们通过线程,试图提高系统内程序并发执行的速度,从而进一步提高系统的吞吐量。
|
|
|
|
|
|
#### 3.4.1 线程的引入
|
|
|
|
|
|
单线程结构的进程给并发程序设计带来了一系列的问题:
|
|
|
|
|
|
+ 进程时空的开销大
|
|
|
+ 进程通信的代价大
|
|
|
+ 进程之间的并发性粒度较粗,并发度不高
|
|
|
+ 不适合并行计算和分布并行计算的要求
|
|
|
+ 不适合客户/服务器计算的要求
|
|
|
|
|
|
解决问题的基本思路:把进程的两项功能——“独立分配资源”和“被调度分派执行分离开来”。前者仍交由进程处理,后者则交给称为线程的实体完成。
|
|
|
|
|
|
#### 3.4.2 线程的基本概念
|
|
|
|
|
|
##### 1.进程与线程的比较
|
|
|
|
|
|
线程具有许多传统进程所具有的特征,所以又称为轻型进程或进程元。
|
|
|
|
|
|
在引入了线程的操作系统中,通常一个进程都拥有若干个进程,至少也有一个进程。
|
|
|
|
|
|
| | 进程 | 线程 |
|
|
|
| -------- | :----------------------------------------------------------- | ------------------------------------------------------------ |
|
|
|
| 调度性 | 传统操作系统中作为独立分派、调度的基本单位。 | 引入线程的操作系统中独立分派、调度的基本单位,而进程则作为资源拥有的基本单位。 |
|
|
|
| 并发性 | 进程之间可以并发执行,但若没有引入线程,当进程阻塞时,整个进程都无法完成其他任务。 | 线程之间同样可以并发执行,进程的一个线程阻塞,其他线程仍可提供服务。 |
|
|
|
| 拥有资源 | 是系统中拥有资源的一个基本单位。 | 虽然拥有一点关键资源,但不算拥有资源的单位。共享进程的资源。 |
|
|
|
| 系统开销 | 创建或撤销进程时系统需要为之创建和回收PCB,分配或回收资源。 | 远小于进程的开销,线程的切换也仅需保存和设置少量寄存器内容。同一个线程中的进程共享地址空间,因此同步和通信也较为容易。 |
|
|
|
|
|
|
线程的状态和状态转换类似于进程,但一部分状态时没有意义的,例如线程没有挂起状态。
|
|
|
|
|
|
##### 2.线程的属性
|
|
|
|
|
|
+ 轻型实体
|
|
|
+ 独立分派调度的基本单位
|
|
|
+ 可并发执行
|
|
|
+ 共享进程资源
|
|
|
|
|
|
线程可以独立调度,但不算是拥有资源的单位。
|
|
|
|
|
|
**线程共享的资源*:**
|
|
|
|
|
|
+ 地址空间
|
|
|
+ 全局变量
|
|
|
+ 打开文件
|
|
|
+ 子进程
|
|
|
+ 信号
|
|
|
|
|
|
**独享的资源*:**
|
|
|
|
|
|
+ 程序计数器
|
|
|
+ 寄存器
|
|
|
+ 栈
|
|
|
+ 状态字
|
|
|
|
|
|
#### 3.4.3 线程管理和线程库*
|
|
|
|
|
|
##### 1.线程状态
|
|
|
|
|
|
每个线程:
|
|
|
|
|
|
+ 线程标识符
|
|
|
+ 一组状态参数
|
|
|
+ 寄存器状态
|
|
|
+ 堆栈
|
|
|
+ 线程运行状态
|
|
|
+ 优先级
|
|
|
+ 线程专存存储器
|
|
|
|
|
|
线程的运行状态:执行、就绪、阻塞。
|
|
|
|
|
|
##### 2.线程的创建和终止
|
|
|
|
|
|
初始化进程:应用程序启动时有的进程
|
|
|
|
|
|
终止:自我终止或他人强制终止
|
|
|
|
|
|
由线程库(用户空间运行/内核中运行)提供的基本线程控制原语:
|
|
|
|
|
|
+ 孵化(spawn)
|
|
|
+ 封锁(block)
|
|
|
+ 活化(unblock)
|
|
|
+ 结束(finish)
|
|
|
|
|
|
##### 3.多线程操作系统中的进程
|
|
|
|
|
|
+ 独立拥有资源
|
|
|
+ 可分为多个线程
|
|
|
+ 不是可运行的实体
|
|
|
|
|
|
#### 3.4.4 线程的实现
|
|
|
|
|
|
##### 1.内核级线程
|
|
|
|
|
|
+ 完全在内核控件实现
|
|
|
+ 内核空间设置线程控股之快
|
|
|
+ 由OS进程线程调度,资源分配等
|
|
|
+ 由OS维护现线程的信息
|
|
|
|
|
|
优点:
|
|
|
|
|
|
+ 多处理器系统中,内核能同时调度同一进程中多个线程并行执行
|
|
|
+ 阻塞线程不会阻塞进程
|
|
|
+ 内核态线程具有很小的数据结构和堆栈,线程切换快,开销小
|
|
|
+ 内核本身可采用多线程技术,提高系统执行速度和效率
|
|
|
|
|
|
缺点:
|
|
|
|
|
|
+ 效率低
|
|
|
+ 内核实现需要占用内存资源
|
|
|
+ 需修改操作系统
|
|
|
|
|
|
##### 2.用户级线程
|
|
|
|
|
|
+ 在用户空间实现
|
|
|
+ 用户空间建立线程库:一组管理线程的进程
|
|
|
+ 用户自己写执行,系统进行调度
|
|
|
+ 线程资源合作
|
|
|
+ 操作系统不知道现成的存在
|
|
|
|
|
|
优点:
|
|
|
|
|
|
+ 线程切换快:不需要陷入内核空间
|
|
|
+ 应用程序特定需要选择调度算法:可选择最好的算法
|
|
|
+ 灵活性:可在任意操作系统实现
|
|
|
|
|
|
缺点:
|
|
|
|
|
|
+ 编程困难
|
|
|
+ 多线程应用不能利用多处理机提高并行效率
|
|
|
+ 系统调用的阻塞问题,线程受阻导致整个进程受阻
|
|
|
|
|
|
如何解决用户级线程的阻塞问题:
|
|
|
|
|
|
+ 修改操作系统
|
|
|
+ 激活受阻进程的其他线程
|
|
|
+ 激活进程调度器
|
|
|
+ 方法:第二次机会法
|
|
|
+ 问题
|
|
|
+ 仍需小幅更改操作系统
|
|
|
+ 违反了操作系统设计的层次结构
|
|
|
|
|
|
##### 3.组合式线程
|
|
|
|
|
|
将内核态和用户态实现结合起来
|
|
|
|
|
|
+ 操作系统管理内核级线程
|
|
|
+ 线程库管理用户态线程
|
|
|
+ 一些用户态线程映射成内核态
|
|
|
|
|
|
##### 4.比较
|
|
|
|
|
|
用户级现成的切换速度更快,但用户级线程系统调用不如内核级线程,同时内核级线程的时间分配更合理。
|
|
|
|
|
|
### 3.5 进程通信(Inter Process Communication)
|
|
|
|
|
|
> 进程通信,是指进程之间的信息交换,其所交换的信息量少者是一个状态或者树脂,多者则是成千上万字节。
|
|
|
|
|
|
进程间的互斥和同步交换的信息量较少,因此被称为低级通信。
|
|
|
|
|
|
信号量机制尽管适合作为同步工具,但作为通信工具有入戏缺点:
|
|
|
|
|
|
+ 效率低
|
|
|
+ 通信对用户不透明
|
|
|
|
|
|
而高级进程通信,是指用户可直接利用操作系统所提供的一组通信命令高效地传送大量数据的一种通信方式。系统实现,隐藏实现细节(即通信过程对用户是透明的)。
|
|
|
|
|
|
#### 3.5.1 进程的通信方式
|
|
|
|
|
|
##### 1.共享存储器系统(shared-memory system)
|
|
|
|
|
|
相互通信的进程共享某些数据结构或共享存储区,进程之间能够通过这些空间进行通信。
|
|
|
|
|
|
+ 共享数据结构,需要设置公用数据结构,处理进程同步。是低效的,只适用于传递相对少量数据。
|
|
|
+ 共享存储区,在存储器中划分出一块共享存储区,进程通过对共享存储区中的读/写实现通信。
|
|
|
|
|
|
##### 2.消息传递系统
|
|
|
|
|
|
消息传递系统(message passing system)是当前应用最广泛的一种进程间的通信机制。该机制中,进程间的数据交换以格式化的消息(message)为单位,计算机网络中又把消息称为报文。程序员直接利用系统提供的通信命令(原语)即可传递大量数据。
|
|
|
|
|
|
+ 直接通信方式
|
|
|
|
|
|
`send(P,message)`,把一个消息发送给进程P
|
|
|
|
|
|
`receive(Q,message)`,从进程Q接收一个消息
|
|
|
|
|
|
+ 间接通信方式(信箱)
|
|
|
|
|
|
进程间发送或接收消息通过一个共享的数据结构——信箱进行。每个信箱有一个唯一的标识符。
|
|
|
|
|
|
`send(A,mail)`,把一封信件(消息)传送到信箱A
|
|
|
|
|
|
`receive(A,mail)`,接受信件,若无信件,则将进程置为等待状态
|
|
|
|
|
|
信箱是存放信件的存储区域,信箱可分为信箱头和信箱体。头储存容量、格式、位置指针等。体存放信件。
|
|
|
|
|
|
##### 3.管道通信系统
|
|
|
|
|
|
管道是指用于连接一个读进程和一个写进程以实现它们之间通信的一个共享文件,又名pipe文件。
|
|
|
|
|
|
管道机制必须提供以下三个方面的协调能力
|
|
|
|
|
|
+ 互斥,一个进程读/写时另一进程等待
|
|
|
+ 同步,一个进程写入一定数据量后,应睡眠等待,读进程取走后再唤醒写入,反之亦然。
|
|
|
+ 确定对方是否存在,确定对方存在时才能进行通信。
|
|
|
|
|
|
### 3.6 进程同步(原3.4)
|
|
|
|
|
|
进程同步的引入:
|
|
|
|
|
|
由于程序的异步性,可能会导致程序执行结果的不一致。
|
|
|
|
|
|
控制进程的执行以及执行顺序称为**进程同步**。
|
|
|
|
|
|
**主要任务**:对多个相关进程在执行次序上进行协调,使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。
|
|
|
|
|
|
#### 3.6.1 进程同步的概念
|
|
|
|
|
|
多道程序环境下,并发执行的程序可能存在如下两种形式的制约关系:
|
|
|
|
|
|
+ 资源共享关系(竞争关系,间接制约关系)
|
|
|
|
|
|
进程共享一套的计算机系统资源,会出现竞争资源的关系。
|
|
|
|
|
|
进程的互斥(mutual exclusion)是解决进程间竞争关系的手段,也成为间接同步。
|
|
|
|
|
|
+ 相互合作关系(协作关系,直接制约关系)
|
|
|
|
|
|
进程为完成一个任务需要分工合作,因为进程的异步性,进程独立地以不可预知地速度推进,这就需要相互协作的进程在某些协调点上协调各自的工作。
|
|
|
|
|
|
进程的同步(synchronization)是解决进程间协作关系的手段,也称直接同步。
|
|
|
|
|
|
进程同步指对进程与进程之间的穿插进行控制。而互斥也是通过逐次使用互斥资源,协调了资源的使用顺序,也是间接地对进程顺序的协调。
|
|
|
|
|
|
#### 3.6.2 临界区及其管理
|
|
|
|
|
|
##### 1.临界资源和临界区
|
|
|
|
|
|
>**临界资源**:一次仅允许一个进程访问的资源
|
|
|
>
|
|
|
>**临界区**:进程访问临界资源的代码段
|
|
|
|
|
|
##### 2.临界区管理
|
|
|
|
|
|
同步机制应当遵循的4个准则:
|
|
|
|
|
|
+ 空闲让进
|
|
|
+ 忙则等待:有一进程进入临界区时,其他进程等待
|
|
|
+ 有限等待
|
|
|
+ 让权等待:等待时应当放弃CPU
|
|
|
|
|
|
##### 3.高级进程同步机制
|
|
|
|
|
|
###### 1.锁(Mutex)
|
|
|
|
|
|
+ 锁阻止了其他进程进入临界区
|
|
|
|
|
|
+ 两个基本操作:
|
|
|
|
|
|
```c++
|
|
|
Lock lock(Lock lock)//等待锁达到打开状态,获得锁并锁上
|
|
|
{
|
|
|
while(1)
|
|
|
{
|
|
|
if(lock.isfree())
|
|
|
{
|
|
|
return lock;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
void unlock(Lock lock){lock.free()};
|
|
|
```
|
|
|
|
|
|
+ 四个基本要素
|
|
|
|
|
|
+ 锁的初始状态要是打开状态
|
|
|
+ 进入临界区前必须获得锁
|
|
|
+ 出临界区时必须打开锁
|
|
|
+ 如果别人持有锁则必须等待
|
|
|
|
|
|
###### 2.睡眠与唤醒
|
|
|
|
|
|
+ `sleep()`原语
|
|
|
+ `wake up()`原语
|
|
|
|
|
|
wake up由其他进程执行。
|
|
|
|
|
|
#### 3.6.3 信号量及PV操作
|
|
|
|
|
|
1965年,E.W.Dijkstra提出了一种卓有成效的进程同步工具:信号量(semaphore)机制。
|
|
|
|
|
|
在信号量机制中,有**检测**(Probern,P,检测,荷兰语)和**归还**(Verhogen,V,增量,荷兰语)两个重要的操作。
|
|
|
|
|
|
+ P操作(wait,down):表示同步进程发出的检测信号量操作,检测是否能够使用临界资源,如果不能使用则等待正在使用的进程归还临界资源
|
|
|
+ V操作(signal,up):将临界资源释放
|
|
|
|
|
|
PV操作都是原子操作。
|
|
|
|
|
|
信号量的类型:
|
|
|
|
|
|
+ 整型信号量
|
|
|
+ 记录型信号量
|
|
|
+ AND型信号量
|
|
|
+ 信号量集
|
|
|
|
|
|
##### 1.整形信号量
|
|
|
|
|
|
设S为一个需要初始化的整形变量,对S的访问仅能通过两个标准的原子操作P(S)和V(S)。
|
|
|
|
|
|
S的初值可为0或1
|
|
|
|
|
|
```c++
|
|
|
void P(int S)
|
|
|
{
|
|
|
while(S<=0){}
|
|
|
S=S-1;
|
|
|
}
|
|
|
void V(int S)
|
|
|
{
|
|
|
S=S+1;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
如果S的值为1,表示有一个临界资源可供使用,P(S)检测通过后,S值被减为0。
|
|
|
|
|
|
如果S值为0,表示没有临界资源,P(S)检测不能通过,进程等待。
|
|
|
|
|
|
由于在等待过程没有放弃CPU控制权,违背了"让权等待"的原则。
|
|
|
|
|
|
记录型信号量解决了这一问题。
|
|
|
|
|
|
##### 2.记录型信号量
|
|
|
|
|
|
让不能进入临界区的进程“让权等待”,进入阻塞队列等待。
|
|
|
|
|
|
设S为一个记录型数据结构,S的定义如下:
|
|
|
|
|
|
```c
|
|
|
#define A 1000
|
|
|
typedef struct semaphore
|
|
|
{
|
|
|
int value;
|
|
|
PCB L[A];//阻塞队列
|
|
|
}Semaphore;
|
|
|
```
|
|
|
|
|
|
相应的,PV操作可描述为:
|
|
|
|
|
|
```c
|
|
|
void P(Semaphore S)
|
|
|
{
|
|
|
S.value-=1;
|
|
|
if(S.value<0) block(S.L);//将调用P的进程阻塞,并放入阻塞队列
|
|
|
}
|
|
|
void V(Semaphore S)
|
|
|
{
|
|
|
S.value+=1;
|
|
|
if(S.value<=0) wakeup(S.L);//从阻塞队列唤醒一个在等待的进程
|
|
|
}
|
|
|
```
|
|
|
|
|
|
##### 3.AND型信号量
|
|
|
|
|
|
上述的进程互斥问题都仅仅针对共享一个临界资源而言。而当进程需要获得两个或更多的临界资源才能完成任务时,有可能由于进程语句顺序不当而造成**死锁**状态,
|
|
|
|
|
|
AND型信号量便是为了解决此类问题。
|
|
|
|
|
|
解决思路:将进程所需要的资源一次性分配。
|
|
|
|
|
|
AND型信号量可定义为:
|
|
|
|
|
|
```c
|
|
|
void P(S1,S2,...,Sn)
|
|
|
{
|
|
|
if(S1>1 && S2>1 && ... && Sn>1)
|
|
|
{
|
|
|
for(int i=0;i<n;i++)
|
|
|
{
|
|
|
Si-=1;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
将进程置于等待队列中等待条件满足;
|
|
|
}
|
|
|
}
|
|
|
void V(S1,S2,...,Sn)
|
|
|
{
|
|
|
for(int i=0;i<n;i++)
|
|
|
{
|
|
|
Si+=1;
|
|
|
唤醒符合条件的线程;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
AND型信号量能够避免死锁,但使并发进程变为先后执行,进程之间相互等待,使得系统整体性能降低。
|
|
|
|
|
|
##### 4.信号量集
|
|
|
|
|
|
用于解决进程一次申请多个同类资源的问题。
|
|
|
|
|
|
信号量集的定义:
|
|
|
|
|
|
+ `S1、S2、...、Sn`表示分别由n类临界资源信号量
|
|
|
+ `t1、t2、...、tn`表示每类临界资源的下限值
|
|
|
+ `d1、d2、...、dn`分别表示进程需要的每类临界资源个数
|
|
|
|
|
|
```c
|
|
|
void P(S1,t1,d1,...,Sn,tn,dn)
|
|
|
{
|
|
|
if(S1>t1 && ... && Sn>tn)
|
|
|
{
|
|
|
for(int i=0;i<=n;i++)
|
|
|
{
|
|
|
Si-=di;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
将当前进程插入Si的等待队列,Si是第一个不满足Si>ti的信号量,程序计数器设为P操作的开始;
|
|
|
}
|
|
|
}
|
|
|
void V(S1,d1,...,Sn,dn)
|
|
|
{
|
|
|
for(int i=0;i<=n;i++)
|
|
|
{
|
|
|
Si+=di;
|
|
|
唤醒Si等待队列的所有进程;
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
三种特例:
|
|
|
|
|
|
`P(S,d,d)`:只有一个信号量S,但允许每次申请d个资源,资源小于d时不分配
|
|
|
|
|
|
`P(S,1,1)`:此时信号量集以及蜕变为一般的记录型信号量
|
|
|
|
|
|
`P(S,1,0)`:特殊且有用的信号量操作,当S>=1时允许多个进程进入特定区,但当S为0后阻止任何进程进入,相当于一个可控开关。
|
|
|
|
|
|
##### 5.信号量的应用
|
|
|
|
|
|
+ 实现进程互斥
|
|
|
+ 描述前趋关系
|
|
|
|
|
|
常见问题:生产者-消费者、哲学家进餐问题、读者-写者问题。
|
|
|
|
|
|
考试时要会利用信号量解决实际问题。
|
|
|
|
|
|
**使用信号量时注意**:
|
|
|
|
|
|
+ PV(wait和signal)必须成对出现。
|
|
|
+ 用于实现互斥的PV必须成对出现在一个程序中,但对资源信号量的PV可能成对出现在不同的程序中。
|
|
|
+ 要注意P操作的顺序,防止进程死锁。
|
|
|
|
|
|
#### 3.6.4 管程*
|
|
|
|
|
|
引入管程的原因:为了避免凡是要使用临界资源的进程都自备同步操作P和V,将同步操作的机制和临界资源结合到一起,形成一种新的同步工具,管程(monitors)。
|
|
|
|
|
|
目的是避免PV过多以及使用不当引起死锁。
|
|
|
|
|
|
##### 1.管程的定义
|
|
|
|
|
|
> 一个数据结构和能够为并发进程所执行的在该数据结构上的一组操作。
|
|
|
|
|
|
##### 2.管程的特性
|
|
|
|
|
|
+ 模块化
|
|
|
+ 抽象数据类型
|
|
|
+ 信息封装
|
|
|
+ 任意时刻,在管程中只能由一个进程
|
|
|
|
|
|
### 3.7 死锁(原3.6)
|
|
|
|
|
|
#### 3.7.1 死锁的定义
|
|
|
|
|
|
多道程序中,多个程序并发执行可能引发一种危险——**死锁**。
|
|
|
|
|
|
> 死锁,是多个进程在运行过程中**争夺资源**而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。
|
|
|
|
|
|
> **资源**:进程运行需要的事物。
|
|
|
|
|
|
#### 3.7.2 产生死锁的原因
|
|
|
|
|
|
进程需要以一种合理的顺序来访问资源
|
|
|
|
|
|
产生死锁的原因:
|
|
|
|
|
|
+ 竞争资源引起死锁
|
|
|
+ 进程间推进次序不当
|
|
|
|
|
|
产生死锁必须满足4个条件:
|
|
|
|
|
|
+ 互斥条件:某资源在一个时间内只能由一个进程占用
|
|
|
+ 持有等待:线程在请求新的资源时,已经获得的资源不释放而是继续持有
|
|
|
+ 不能抢占:不能强迫进程放弃资源
|
|
|
+ 环路等待
|
|
|
|
|
|
#### 3.7.3 处理死锁的方法
|
|
|
|
|
|
处理死锁的方法可归结为:
|
|
|
|
|
|
+ 不予理睬:忽略问题的存在
|
|
|
+ 此种策略在如下情况下合理:
|
|
|
+ 死锁出现的概率很低
|
|
|
+ 预防死锁的代价很大
|
|
|
+ UNIX和windows都采用此方法
|
|
|
+ 是方便和正确性的一种折中
|
|
|
+ 静态预防:消除死锁的4个必要条件的任意一个
|
|
|
+ 消除资源独占条件
|
|
|
+ 一些设备可以被共享
|
|
|
+ 但不是所有设备都可以被共享
|
|
|
+ 消除持有等待条件
|
|
|
+ 进程启动时请求所有资源
|
|
|
+ 缺点:资源浪费、可能无法得知所需的所有资源
|
|
|
+ 消除非抢占条件
|
|
|
+ 允许抢占CPU(信息保存到进程控制表)/内存(内存导出到硬盘)
|
|
|
+ 局限性:有些资源不可被抢占:如锁、打印机
|
|
|
+ 消除环路等待条件
|
|
|
+ 指定需要资源的顺序
|
|
|
+ 或增加资源,最小化死锁的概率
|
|
|
+ 动态避免:仔细地资源分配
|
|
|
+ 死锁检测、解除死锁:成对地解决方法,在死锁发生后采取措施纠正
|
|
|
|
|
|
#### 3.7.4 死锁检测和修复*
|
|
|
|
|
|
注意资源的占有和资源需求。
|
|
|
|
|
|
资源分配图以及检测:
|
|
|
|
|
|
+ 有向图检测
|
|
|
+ 矩阵检测
|
|
|
|
|
|
死锁的恢复:
|
|
|
|
|
|
+ 剥夺资源
|
|
|
+ 杀死进程
|
|
|
|
|
|
#### 3.7.5 死锁的动态避免(银行家算法)
|
|
|
|
|
|
Dijkstra在1965年提出了银行家算法,源于银行家发放贷款时采取的控制方法。
|
|
|
|
|
|
+ 事先声明所需的最大资源(但实际并不获得最大资源)
|
|
|
+ 在之后进程请求资源时
|
|
|
+ 若分配资源后仍处于**安全状态**,满足要求
|
|
|
+ 否则阻塞进程
|
|
|
|
|
|
银行家算法的数据结构:
|
|
|
|
|
|
+ 可利用资源向量Available
|
|
|
|
|
|
例:`Available={3,3,2}`
|
|
|
|
|
|
| A | B | C |
|
|
|
| :--: | :--: | :--: |
|
|
|
| 3 | 3 | 2 |
|
|
|
|
|
|
其中的每个元素代表一类可利用的资源数目
|
|
|
|
|
|
`Available[j]=k`代表系统现有`Rj`类资源`k`个
|
|
|
|
|
|
+ 最大需求矩阵Max
|
|
|
|
|
|
例:`Max={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}}`
|
|
|
|
|
|
| 进程\资源 | A | B | C |
|
|
|
| :-------: | :--: | :--: | :--: |
|
|
|
| P0 | 7 | 5 | 3 |
|
|
|
| P1 | 3 | 2 | 2 |
|
|
|
| P2 | 9 | 0 | 2 |
|
|
|
| P3 | 2 | 2 | 2 |
|
|
|
| P4 | 4 | 3 | 3 |
|
|
|
|
|
|
是一个n*m矩阵,表示系统中n个进程的每一个进程对m类资源的最大需求。
|
|
|
|
|
|
+ 分配矩阵Allocation
|
|
|
|
|
|
也是一个n*m矩阵,表示当前每一类资源已经分配给进程的资源数
|
|
|
|
|
|
+ 需求矩阵Need
|
|
|
|
|
|
同样是一个n*m矩阵,用以表示每一个进程尚需的各类资源数
|
|
|
|
|
|
`Need[i][j]=Max[i][j]-Allocation[i][j]`
|
|
|
|
|
|
银行家算法流程:
|
|
|
|
|
|
+ 对于请求向量Request进行检测,若请求的资源大于需求资源Need,则拒绝
|
|
|
+ 若请求的资源大于可用资源Available,拒绝,没有足够资源分配,需要等待
|
|
|
+ 试探性分配资源并进行**安全性检测**,若分配后状态安全,则进行分配,否则拒绝
|
|
|
|
|
|
安全性算法(简要自然语言描述):
|
|
|
|
|
|
若能找到一个序列,系统的剩余资源能按次序完成(一个进程完成后,拥有的全部资源会归还)每个进程的请求,则当前状态安全。
|
|
|
|
|
|
**考试要求**:要会使用银行家算法对Request进行分析。
|
|
|
|
|
|
---
|
|
|
|
|
|
# 第四章 处理机调度
|
|
|
|
|
|
处理机是计算机系统中的重要资源,在多道程序环境下,进程数目>处理机。系统需要按照一定方法动态地分配给就绪队列。处理机利用率和系统性能很大程序取决于处理机调度。
|
|
|
|
|
|
**处理机调度是操作系统设计的中心问题之一。**
|
|
|
|
|
|
+ WHAT:按什么分配
|
|
|
+ WHEN:何时分配CPU
|
|
|
+ HOW:如何分配CPU
|
|
|
|
|
|
> **处理机调度**:指在多道程序环境中将处理机分配给进程。
|
|
|
|
|
|
### 4.1 处理机调度的层次
|
|
|
|
|
|
> **作业**是用户在一次解题或一个事务处理过程中要求计算机系统所作工作的集合,包括用户程序、所需的数据及命令等。
|
|
|
|
|
|
作业的状态:后备、运行、完成。
|
|
|
|
|
|
![作业的状态转换](http://47.117.160.245:8080/pictrue/private/os_03.png)
|
|
|
|
|
|
#### 4.1.1 高级调度
|
|
|
|
|
|
> 高级调度也称为**作业调度**、**长程调度**或接纳调度。
|
|
|
>
|
|
|
> 主要任务是为作业分配内存、资源,放入就绪队列。
|
|
|
|
|
|
每次作业调度时,需决定:
|
|
|
|
|
|
+ 接纳多少个作业
|
|
|
|
|
|
取决于多道程序度,即允许多少个作业同时在内存中运行
|
|
|
|
|
|
+ 作业太多:服务质量下降
|
|
|
+ 作业太少:资源利用率低
|
|
|
|
|
|
+ 接纳哪些作业
|
|
|
|
|
|
取决于作业调度算法:
|
|
|
|
|
|
+ 先来先服务
|
|
|
+ 短作业优先
|
|
|
+ 作业优先权调度
|
|
|
+ 响应比调度
|
|
|
|
|
|
#### 4.1.2 低级调度
|
|
|
|
|
|
> 低级调度也称为**进程调度**或**短程调度**
|
|
|
>
|
|
|
> 主要任务是按某种策略和方法选取一个就绪进程,分配处理机
|
|
|
|
|
|
低级调度分为**抢占式**和**非抢占式**两种。
|
|
|
|
|
|
+ 非抢占式:当前进程不会被优先级更高的进程抢占
|
|
|
|
|
|
引起进程调度的因素
|
|
|
|
|
|
+ 正在执行的进程执行完毕,或因发生某事件不能继续执行。
|
|
|
+ 执行中的进程因I/O暂停
|
|
|
+ 进程执行了某种原语操作,如`wait`/`block`
|
|
|
|
|
|
**优点**:算法简单,系统开销小
|
|
|
|
|
|
**缺点**:紧急任务不能及时响应;短进程等待长进程
|
|
|
|
|
|
+ 抢占式
|
|
|
|
|
|
若有某个更为重要或紧迫的进程进入就绪队列,则暂停当前进程,将处理机分配给这个更为重要或紧迫的进程。
|
|
|
|
|
|
抢占式调度主要有以下原则
|
|
|
|
|
|
+ 优先权原则
|
|
|
+ 短进程优先原则
|
|
|
+ 时间片原则(分配的时间片用完后停止执行)
|
|
|
|
|
|
**优点**:适用于时间要求严格的实时系统
|
|
|
|
|
|
**缺点**:调度算法复杂,系统开销大
|
|
|
|
|
|
低级调度的时间尺度往往是毫秒级的,由于频繁使用因此要求在实现时做到高效。
|
|
|
|
|
|
#### 4.1.3 中级调度
|
|
|
|
|
|
> 中级调度也称为中程调度
|
|
|
|
|
|
引入目的:提高内存利用率和系统吞吐量
|
|
|
|
|
|
主要任务:按照给定的原则和策略,交换内存和外存
|
|
|
|
|
|
#### 4.1.4 处理机调度的目标(原4.3.1)
|
|
|
|
|
|
+ 对于I/O密集型程序,极小化平均响应时间
|
|
|
+ 平均化做每项工作的时间
|
|
|
+ 对于计算密集型程序,极大化系统吞吐量
|
|
|
+ 单位时间内完成尽可能多的程序
|
|
|
+ 对于平衡性程序,响应时间和周转时间达到平衡
|
|
|
|
|
|
#### 4.1.5 不同系统的调度目标(原4.3.1)
|
|
|
|
|
|
+ 批处理系统
|
|
|
+ 系统吞吐率:最大化单位时间的工作量
|
|
|
+ 周转时间:最小化任务提交到结束之前的时间
|
|
|
+ CPU利用率:保证CPU始终在繁忙工作状态
|
|
|
+ 交互式系统
|
|
|
+ 快速响应需求
|
|
|
+ 满足用户期望
|
|
|
+ 实时系统
|
|
|
+ 截止时间内满足需求
|
|
|
+ 避免丢失数据
|
|
|
+ 提供性能可预测性
|
|
|
|
|
|
### 4.2 调度队列模型及调度准则*
|
|
|
|
|
|
#### 4.2.1 调度队列模型
|
|
|
|
|
|
+ 仅有进程调度的调度队列模型
|
|
|
+ 具有高级和低级调度的调度队列形式(批处理系统)
|
|
|
+ 同时具有三级调度的调度队列模型
|
|
|
|
|
|
#### 4.2.2 选择调度方式和算法的若干准则
|
|
|
|
|
|
##### 1.面向用户的准则
|
|
|
|
|
|
+ 周转时间短(周转时间:完成时间-到达时间,带权:周转时间/服务时间)
|
|
|
+ 响应时间快(交互性作业)
|
|
|
+ 截止时间的保证(特别是对于实时系统)
|
|
|
+ 优先权准测
|
|
|
|
|
|
##### 2.面向系统的准则
|
|
|
|
|
|
+ 吞吐量高(特别是对于批处理系统)
|
|
|
+ 处理机利用率好
|
|
|
+ 各类资源的平衡利用
|
|
|
|
|
|
### 4.3 调度算法
|
|
|
|
|
|
#### 4.3.1 先来先服务
|
|
|
|
|
|
> **先来先服务**(First come, First serve, FCFS)是最简单的非抢占式调度算法,它是指按照作业或进程进入系统的先后次序进行调度。
|
|
|
|
|
|
先进入系统者先调度,即启动等待时间最长的进程。既可用于作业调度,也可用于进程调度。
|
|
|
|
|
|
**优缺点:**
|
|
|
|
|
|
+ 有利于长作业(进程),而不利于短作业(进程)
|
|
|
+ 有利于CPU繁忙型进程(作业),而不利于I/O繁忙型进程(作业)
|
|
|
+ 用于批处理系统,不适用于分时系统
|
|
|
|
|
|
#### 4.3.2 短作业(进程)优先调度算法
|
|
|
|
|
|
> **短作业(进程)优先调度算法**(short job first,SJF/short process first,SPF)是指以运行时间长短进行调度,启动运行时间最短的作业(进程)。
|
|
|
|
|
|
**优缺点:**
|
|
|
|
|
|
+ 能够降低平均周转时间和平均带权周转时间
|
|
|
+ 对长作业不利,长作业长期不被调度引发饥饿
|
|
|
+ 没有考虑作业的紧迫程度
|
|
|
+ 运行时间仅能估算,实际会有变动
|
|
|
|
|
|
#### 4.3.3 高优先权调度算法
|
|
|
|
|
|
> 为了照顾紧迫作业,使之在进入系统后便获得优先处理,引入了**最高优先权优先**(first priority first, FPF)算法。
|
|
|
|
|
|
分为抢占式(会立即结束当前进程)和非抢占式。
|
|
|
|
|
|
都会把处理机分配给最高优先权的进程,当有更高优先权的进程到达时,抢占式算法将立即停止当前进程的执行,处理机分配给优先权最高的进程,非抢占式算法将不会比较优先级,首先将当前进程执行完毕。
|
|
|
|
|
|
确定进程优先权的依据有以下三个方面:
|
|
|
|
|
|
+ 进程类型
|
|
|
+ 进程对资源需求
|
|
|
+ 用户要求
|
|
|
|
|
|
优先权的类型:
|
|
|
|
|
|
+ 静态优先权:在创建进程时确定
|
|
|
+ 系统开销小
|
|
|
+ 不够精确
|
|
|
+ 动态优先权
|
|
|
+ 随着进程的推进/等待时间的增加而改变
|
|
|
+ 可规定就绪队列中的进程随等待时间增长,优先权提高
|
|
|
+ 在抢占式FPF中,也可规定执行中的进程随执行时间增长,优先权降低
|
|
|
|
|
|
#### 4.3.4 高响应比优先调度算法
|
|
|
|
|
|
是FCFS和SJF的结合
|
|
|
|
|
|
> **高响应比优先调度算法**(Highest Response Ratio First, HRF)的调度策略是使响应比最高的作业优先启动。
|
|
|
|
|
|
优先权=响应时间(等待时间+服务时间)/服务时间
|
|
|
|
|
|
等待时间相同的作业,要求服务时间越短,优先权更高
|
|
|
|
|
|
服务时间想通过的作业,等待时间越航,优先权越高
|
|
|
|
|
|
优先权随等待时间增加而提高
|
|
|
|
|
|
是一种折衷,既照顾了短作业,又考虑了到达的先后次序
|
|
|
|
|
|
**缺点**:要进行响应比计算,增加了系统开销
|
|
|
|
|
|
#### 4.3.5 简单的时间片轮转算法
|
|
|
|
|
|
> **时间片轮转**(Round Robin, RR)是指系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时给队首分配一个时间片。时间片用完时加入队尾。
|
|
|
|
|
|
**缺点**:紧迫任务响应时间慢
|
|
|
|
|
|
#### 4.3.6 多级反馈队列调度算法
|
|
|
|
|
|
是目前公认的一种较好的进程调度算法。
|
|
|
|
|
|
> 设置多个就绪队列,并为各个队列赋予不同的优先级
|
|
|
>
|
|
|
> + 第一个队列优先级最高,之后依次降低
|
|
|
> + 第一个队列分配的时间片最短,之后依次加长
|
|
|
> + 第一个队列分配的时间片用完后,置入第二个队列,以此类推
|
|
|
|
|
|
![调度过程](http://47.117.160.245:8080/pictrue/private/os_04.png)
|
|
|
|
|
|
多级反馈队列调度算法具有较好的性能,能很好地满足各种类型用户的需要。
|
|
|
|
|
|
### 4.4 实时调度
|
|
|
|
|
|
先前的调度算法关注平均化的分析,而对于实时系统,必须保证在截止时间前完成任务(例:视频输入,物理控制系统)
|
|
|
|
|
|
#### 4.4.1 实时调度的基本条件
|
|
|
|
|
|
+ 提供必要的调度信息
|
|
|
+ 就绪时间
|
|
|
+ 开始/完成截止时间
|
|
|
+ 处理时间
|
|
|
+ 资源要求
|
|
|
+ 优先级
|
|
|
+ 系统处理能力强
|
|
|
+ 具有快速切换机制
|
|
|
|
|
|
#### 4.4.2 常用的几种实时调度算法
|
|
|
|
|
|
##### 1.最早截止时间优先(EDF)
|
|
|
|
|
|
总是运行最早结束的作业
|
|
|
|
|
|
##### 2.最低松弛度优先(LLF)
|
|
|
|
|
|
松弛度:A需在200ms前完成,运行需100ms,当前10ms,则A的松弛度为200-100-10=90ms
|
|
|
|
|
|
### 4.5 进程调度的时机
|
|
|
|
|
|
+ 当一个进程运行完毕,或由于某种错误而终止运行
|
|
|
+ 当一个进程在运行中处于等待状态(阻塞)
|
|
|
+ 分时系统中时间片到
|
|
|
+ 有一个优先级更高的进程就绪
|
|
|
+ 进程执行了某种原语
|
|
|
|
|
|
---
|
|
|
|
|
|
# 第五章 存储管理
|
|
|
|
|
|
### 5.1 存储器
|
|
|
|
|
|
#### 5.1.1 存储器的层次结构
|
|
|
|
|
|
实际情况的内存架构:
|
|
|
|
|
|
+ CPU寄存器:低容量、高速度、高价格
|
|
|
+ 高速缓存
|
|
|
+ 主存(内存):中容量、中速度、中价格
|
|
|
+ 内存的大小是衡量计算机性能的一个非常重要的指标
|
|
|
+ 辅存(外存):大容量、低速度、低成本
|
|
|
|
|
|
不同层次的存储介质,均有操作系统进行统一管理,存储管理主要负责内存、高速缓存的管理,外存的管理则交由设备和文件管理负责。
|
|
|
|
|
|
> 计算机中的内存也称为物理内存,其地址从最低开始到最高上界,按照顺序编号。内存中的地址称为**物理地址**。
|
|
|
|
|
|
而在操作系统中,存储管理功能负责为进程分配和回收内存,实现内存空间在时间和空间上的复用。
|
|
|
|
|
|
#### 5.1.2 程序的装入和链接*
|
|
|
|
|
|
+ 用户用高级语言编写的源程序,需要经过编译、链接和装入后,才能被处理器运行。
|
|
|
|
|
|
> 程序装入内存前,装入模块中给出的程序地址为程序的**逻辑地址**,一个用户的所有装入模块的逻辑地址集合称为该作业的**逻辑地址空间**。
|
|
|
>
|
|
|
> 用户作业被装入内存后,进程物理地址的总体构成了**物理地址空间**。
|
|
|
>
|
|
|
> 为保证用户作业的正确运行,必须把用户作业的逻辑地址转化为物理地址,这一过程称为**地址变换**或**重定位**。
|
|
|
|
|
|
+ **编译**是将用户用高级语言编写的源程序转化为目标模块
|
|
|
+ **链接**将用户需要的所有目标模块链接在一起,形成一个可执行模块,即装入模块
|
|
|
+ 静态链接:链接过程在程序装入内存前完成,形成整个程序的逻辑地址空间
|
|
|
+ 装入时动态链接
|
|
|
+ 便于模块修改和更新
|
|
|
+ 便于目标模块的共享
|
|
|
+ 运行时动态链接
|
|
|
+ 不运行的模块,不需要链接
|
|
|
+ **装入**将装入模块放入内存
|
|
|
+ 绝对装入方式:对程序员要求很高,适合用于实时操作系统和嵌入式操作系统
|
|
|
+ 静态重定位装入方式
|
|
|
+ 动态重定位装入方式:可以在程序运行时重新定位程序在内存中的地址,以便于虚拟存储器等功能
|
|
|
|
|
|
#### 5.1.3 存储器管理的两个目标
|
|
|
|
|
|
+ 地址独立:程序发出的地址与物理主存地址无关
|
|
|
+ 地址保护:一个进程不能访问另一个进程的地址空间
|
|
|
|
|
|
### 5.2 连续存储空间管理
|
|
|
|
|
|
> 连续存储空间,是指为一个用户程序分配一个连续的内存空间
|
|
|
|
|
|
可进一步划分为:
|
|
|
|
|
|
+ 单一连续分配
|
|
|
+ 最早出现,应用于单道编程
|
|
|
+ 固定分区分配
|
|
|
+ 应用于多道编程
|
|
|
+ 动态分区分配
|
|
|
+ 应用于多道编程
|
|
|
+ 动态分区重定位
|
|
|
|
|
|
#### 5.2.1 单一连续分配
|
|
|
|
|
|
+ 是最简单的存储管理方式,只用于单用户、单任务的系统中。
|
|
|
|
|
|
+ 内存分为系统区和用户区
|
|
|
+ 系统区仅提供给操作系统使用
|
|
|
+ 用户区提供给用户使用
|
|
|
+ 达到了地址独立
|
|
|
+ 达到了地址保护(整个系统只有一个用户程序)
|
|
|
+ 问题
|
|
|
+ 将整个程序加载到内存空间
|
|
|
+ 浪费资源
|
|
|
|
|
|
#### 5.2.2 固定分区分配
|
|
|
|
|
|
+ 多道编程中最简单的内存管理方式
|
|
|
+ 将内存划分为几个固定的区域,可同时装入多个作业/任务
|
|
|
+ 程序被加载到固定的分区
|
|
|
+ 分区大小
|
|
|
+ 大小相等:缺乏灵活性
|
|
|
+ 大小不等:多个较小分区,适量中等分区以及少量大分区
|
|
|
+ 分配到分区的选择
|
|
|
+ 每个分区一个进程队列,每个队列进入固定分区
|
|
|
+ 单一输入队列,新进程可以进入任意分区
|
|
|
+ 固定分区分配的地址变换也有静态重定位方式和动态重定位方式
|
|
|
+ 地址变换借助于下限寄存器和上限寄存器
|
|
|
+ 进程的逻辑地址+下限寄存器中的基址为物理地址
|
|
|
+ 若物理地址落入上下限寄存器地址中则有效,否则访问越界,拒绝分配分区
|
|
|
+ 缺点:
|
|
|
+ 内存利用率不高(内存碎片)
|
|
|
+ 划分分区大小困难
|
|
|
+ 需要预先知道进程大小
|
|
|
|
|
|
#### 5.2.3 动态分区分配
|
|
|
|
|
|
+ 根据作业的实际需要,动态地为其分配内存空间
|
|
|
|
|
|
+ 为了完成分配和回收分区,需要构建对分区信息描述地数据结构,并完成分区分配算法与回收方法
|
|
|
|
|
|
+ 数据结构
|
|
|
|
|
|
+ 空闲分区表:包括分区号、分区始址,分区大小
|
|
|
+ 空闲分区链:空闲分区最常用地组织形式,所有地空闲分区通过前向和后向指针串在一起组成双向空闲分区链
|
|
|
|
|
|
+ 分区分配算法
|
|
|
|
|
|
+ 首次适应法
|
|
|
|
|
|
+ 空闲分区链按照地址递增的顺序组织
|
|
|
+ 每次分配内存时,遍历分区链,找到满足大小分区时分割一部分给程序
|
|
|
+ 找不到则分配失败
|
|
|
|
|
|
**缺点**:大空闲分区被分割、每次查找都从链首开始,增加了查找的开销
|
|
|
|
|
|
+ 循环首次适应法
|
|
|
|
|
|
+ 空闲分区链按照地址递增的顺序组织
|
|
|
+ 每次分配内存时,从空闲分区链上上次为作业分配分区后的位置开始查找
|
|
|
|
|
|
克服了空闲空间分布不均的问题,但碎片空间问题仍没有得到解决
|
|
|
|
|
|
+ 最佳适应算法
|
|
|
|
|
|
+ 空闲分区链按照分区大小递增的顺序组织
|
|
|
+ 从分区链中挑选一个满足进程要求的最小分区进行分配
|
|
|
|
|
|
是一种较优的分区分配算法,但剩余的空闲分区很小,这一部分很小的碎片,难以再次利用
|
|
|
|
|
|
+ 最坏适应算法
|
|
|
|
|
|
+ 空闲分区链按照分区大小递减的顺序进行组织
|
|
|
+ 从分区链中挑选一个满足作业要求的最大分区
|
|
|
|
|
|
系统会缺乏较大的空闲分区
|
|
|
|
|
|
+ 快速适应算法
|
|
|
|
|
|
+ 空闲分区根据容量大小进行分类,单独设立空闲分区链
|
|
|
+ 内存中设一张管理索引表,每一个表对应了空闲分区类型
|
|
|
+ 分配时根据大小从对应索引表找到对应空闲分区链的起始指针,开始查找分配
|
|
|
|
|
|
该算法查找效率高,对大的作业不会产生内存碎片
|
|
|
|
|
|
缺点是回收分区困难,算法复杂,系统开销大
|
|
|
|
|
|
+ 分区分配和回收操作
|
|
|
|
|
|
+ 分区分配:首先根据分配算法中查找所需大小的分区。分区分配成功后会将分配区的首地址返回给分配过程的调用者。
|
|
|
|
|
|
+ 分区回收:作业完成时会释放内存,系统需要回收,**回收的内存进入空闲分区链才能再次分配**。
|
|
|
|
|
|
根据分区的首地址,有四种不同的情况:
|
|
|
|
|
|
+ 上邻空闲区:合并,修改大小
|
|
|
+ 下邻空闲区:合并,修改大小、首地址
|
|
|
+ 上下邻空闲区:合并,修改大小
|
|
|
+ 不邻接:建立一新表项插入空闲链的适当位置
|
|
|
|
|
|
+ 存在的问题
|
|
|
|
|
|
+ 难以增长进程空间(如栈,数据等)
|
|
|
|
|
|
解决方案:为增长的栈和数据段分配空间
|
|
|
|
|
|
#### 5.2.4 可重定位分区分配
|
|
|
|
|
|
动态重定位的引入:连续分配方式中,总量大于作业大小的多个小分区不能容纳作业。
|
|
|
|
|
|
通过作业移动将小分区拼接成大分区,作业的移动需要重定位。
|
|
|
|
|
|
#### 5.2.5 对换
|
|
|
|
|
|
> 对换:把内存中暂时不能运行的进程或者暂时不用的程序和数据调出到外存上,以便腾出足够的内存空间
|
|
|
>
|
|
|
> 整体对换:进程对换
|
|
|
>
|
|
|
> 部分对换:分页对换
|
|
|
|
|
|
为实现进程对换,系统须实现三方面功能:
|
|
|
|
|
|
+ 对换空间的管理
|
|
|
+ 进程的换出
|
|
|
+ 进程的换入
|
|
|
|
|
|
外存
|
|
|
|
|
|
+ 文件区:注重空间利用率,一般采用离散存储方式
|
|
|
+ 对换区:注重速度,采用连续分配方式
|
|
|
|
|
|
换出
|
|
|
|
|
|
+ 选择被换出进程:考虑进程状态、优先级、驻留时间
|
|
|
+ 换出过程:若为共享段,必须计数-1后为0(没有进程需要)才换出,否则不换出。修改PCB。
|
|
|
|
|
|
换入
|
|
|
|
|
|
+ 选择换入进程:考虑进程就绪、优先级、换出时间
|
|
|
+ 申请内存
|
|
|
+ 换入
|
|
|
|
|
|
连续分配方式的问题:
|
|
|
|
|
|
+ 很难增长地址空间
|
|
|
+ 不能运行大于物理内存的程序
|
|
|
+ 外部碎片
|
|
|
|
|
|
如何解决以上问题?分页。
|
|
|
|
|
|
### 5.3 分页存储管理
|
|
|
|
|
|
#### 5.3.1 分页存储管理的基本思想
|
|
|
|
|
|
+ 将物理内存分配成固定大小的块(或页框)
|
|
|
+ 固定单元易于分配
|
|
|
+ 任何空闲物理页可以存储任何逻辑页
|
|
|
+ 将逻辑空间分成相同大小的页
|
|
|
+ 每个逻辑页可以存在物理内存上或导出到磁盘上
|
|
|
+ 进程通过逻辑地址访问内存
|
|
|
+ 页面大小不能太大(导致碎片)也不能太小(页表过长,效率低),一般是512B~8K
|
|
|
|
|
|
#### 5.3.2 分页系统中的地址结构
|
|
|
|
|
|
+ 页面号
|
|
|
+ 页内偏移量
|
|
|
|
|
|
通过页表实现逻辑页面和物理块之间的映射关系
|
|
|
|
|
|
处理器可以通过**页表的一个有效/无效位**知道逻辑页面是否在物理内存中
|
|
|
|
|
|
页面可以有不同的保护方式(可读、可写、可执行),这些信息也**保存在页表中**
|
|
|
|
|
|
##### 1.页表
|
|
|
|
|
|
+ 页表是分页系统的关键组成组件
|
|
|
+ 是一个硬件数据结构,实现逻辑页面和物理块之间的映射关系
|
|
|
+ 页表内容:
|
|
|
+ 是否存在物理内存中的标志位、
|
|
|
+ 物理页面号
|
|
|
+ 修改位:加载后是否被修改过
|
|
|
+ 访问位:页面被读/写
|
|
|
+ 保护位
|
|
|
|
|
|
##### 2.页面翻译过程
|
|
|
|
|
|
```
|
|
|
块内偏移=页内偏移
|
|
|
物理地址=块号*块长+块内偏移
|
|
|
```
|
|
|
|
|
|
##### 3.地址变换机构
|
|
|
|
|
|
**基本任务**:实现从逻辑地址到物理地址的转换
|
|
|
|
|
|
借助页表完成,页表大多驻留内存
|
|
|
|
|
|
每个进程对应一个页表,未执行时其信息放入PCB中,执行时将页表的首地址装入页表寄存器。
|
|
|
|
|
|
系统只设置一个页表寄存器,存放页表在内存的首地址和页表长度
|
|
|
|
|
|
![地址变换机构](http://47.117.160.245:8080/pictrue/private/os_05.png)
|
|
|
|
|
|
分页系统存在的问题:页表的尺寸可能很大
|
|
|
|
|
|
解决方案:使用二级/多级页表
|
|
|
|
|
|
#### 5.3.3 两级和多级页表
|
|
|
|
|
|
一级页表存放二级页面的信息,......
|
|
|
|
|
|
最后一级存放对应的物理地址
|
|
|
|
|
|
地址的转化:
|
|
|
|
|
|
一级->二级->地址+偏移
|
|
|
|
|
|
使用多级页表会增加内存的访问次数
|
|
|
|
|
|
#### 5.3.4 快表
|
|
|
|
|
|
> 翻译快表,缩写为TLB(Translation Look-Aside Buffer),用于加快地址翻译的过程。
|
|
|
|
|
|
+ 加快了内存访问速度
|
|
|
+ 缓存了从虚拟页面到物理页面的映射
|
|
|
|
|
|
具有快表的地址变换过程:先查询快表,若该页不在快表中,则再查询页表,并把该页的映射写入快表,快表若已满,则换出很久未查询的映射。
|
|
|
|
|
|
![快表的地址变换](http://47.117.160.245:8080/pictrue/private/os_06.png)
|
|
|
|
|
|
分页系统的缺陷:
|
|
|
|
|
|
+ 共享困难:页面中只要有一行地址不能共享,整个页面就不能共享
|
|
|
+ 每个进程占用一个虚拟地址空间,可能发生碰撞
|
|
|
|
|
|
解决方案:分段。
|
|
|
|
|
|
### 5.4 分段存储管理
|
|
|
|
|
|
#### 5.4.1 分段存储管理的引入
|
|
|
|
|
|
为了满足下列一系列需要
|
|
|
|
|
|
+ 方便编程
|
|
|
+ 分段共享
|
|
|
+ 分段保护
|
|
|
+ 动态链接
|
|
|
+ 动态增长
|
|
|
|
|
|
#### 5.4.2 分段系统的基本原理
|
|
|
|
|
|
+ 分段系统把一个程序按照逻辑单元分成多个程序段
|
|
|
|
|
|
+ 每一段使用自己单独的虚地址空间
|
|
|
|
|
|
+ 依旧是离散的存储方式
|
|
|
|
|
|
+ 注意:并不是所有虚拟地址都有效
|
|
|
|
|
|
+ 有效意味着该区域是进程虚拟地址空间的一部分
|
|
|
+ 无效意味着虚拟地址是非法的
|
|
|
|
|
|
物理地址=基址+段内偏移
|
|
|
|
|
|
+ 保护:不同的段可以有不同的保护
|
|
|
|
|
|
+ 使用段表储存分段信息
|
|
|
|
|
|
| 分页 | 分段 |
|
|
|
| :--------------------------: | :--------------------------: |
|
|
|
| 提高内存利用率 | 满足用户需要 |
|
|
|
| 一个线性地址空间 | 多个线性地址空间 |
|
|
|
| 整个地址空间可以超过内存尺寸 | 整个地址空间可以超过内存尺寸 |
|
|
|
| 程序和数据不可单独保护 | 可以实现单独保护程序数据 |
|
|
|
| 尺寸不易变化 | 尺寸容易变化 |
|
|
|
| 不可以共享程序 | 可以共享程序 |
|
|
|
|
|
|
如何结合两者优点:段页式内存管理
|
|
|
|
|
|
+ 将程序分为多个逻辑段
|
|
|
+ 每个段里又进行分页
|
|
|
|
|
|
![段页式存储管理](http://47.117.160.245:8080/pictrue/private/os_07.png)
|
|
|
|
|
|
段页式地址管理的地址变换机构:
|
|
|
|
|
|
![引入挂起的状态转换](http://47.117.160.245:8080/pictrue/private/os_08.png)
|
|
|
|
|
|
### 5.5 虚拟存储器管理
|
|
|
|
|
|
#### 5.5.1 虚拟存储器的概念
|
|
|
|
|
|
计算机系统的内存容量是有限的,而传统存储器管理中,如果一个作业要运行,作业的全部信息必须装入内存。这限制了运行作业的大小以及数量。通过研究发现,进程执行时并非同时需要作业的全部信息,可以将这些暂时不使用的信息调出内存。
|
|
|
|
|
|
> 将外存作为内存的补充,从逻辑上扩充内存,是虚拟存储管理的基本思想
|
|
|
|
|
|
程序和数据的访问具有如下特点:
|
|
|
|
|
|
+ 顺序性
|
|
|
+ 局限性
|
|
|
+ 多次性
|
|
|
+ 独立性
|
|
|
|
|
|
> **虚拟存储器**的定义:是指具有请求调入功能和置换功能,能够从逻辑上对内存空间进行扩展,允许用户的逻辑地址空间大于物理内存地址空间的存储管理系统。
|
|
|
|
|
|
+ 虚拟存储器中,一般将硬盘作为外存,因此,硬盘也被称为对换设备
|
|
|
+ 虚拟存储器的基础是内存的离散管理,实现的方式为**请求分页式虚拟存储器管理**或**请求分段式虚拟存储器管理**
|
|
|
+ 请求分页式虚拟存储器管理
|
|
|
+ 以页为单位置换
|
|
|
+ 需硬件支持
|
|
|
+ 请求分页的页表机构
|
|
|
+ 缺页中断机构
|
|
|
+ 地址变化机构
|
|
|
+ 需实现请求分页的软件
|
|
|
+ 用于实现请求调页的软件
|
|
|
+ 实现页面置换的软件
|
|
|
+ 请求分段式虚拟存储器管理
|
|
|
+ 以段为单位置换
|
|
|
+ 需硬件支持
|
|
|
+ 请求分段的段表机构
|
|
|
+ 缺段中断机构
|
|
|
+ 地址变化机构
|
|
|
+ 需实现请求分段的软件
|
|
|
+ 用于实现请求调段的软件
|
|
|
+ 实现段面置换的软件
|
|
|
+ 虚拟存储器的特征
|
|
|
+ 多次型:最重要的特征
|
|
|
+ 对换性
|
|
|
+ 虚拟性
|
|
|
|
|
|
#### 5.5.2 请求分页式虚拟存储器管理
|
|
|
|
|
|
基于内存的分页管理,需要增加**请求调页**和**页面置换**功能。
|
|
|
|
|
|
**请求调页**和**页面置换**也是虚拟存储管理的主要功能。
|
|
|
|
|
|
##### 1.请求分页的页表机制
|
|
|
|
|
|
除了页号和物理块号外,增加了页的状态位,外存地址,修改为,访问字段
|
|
|
|
|
|
+ 状态位:用于标志一个页面是否已经装入内存
|
|
|
+ 外存地址:页面在外存中的地址
|
|
|
+ 修改位:调入后是否修改过的标志
|
|
|
+ 访问字段:在内存中是否被访问过
|
|
|
|
|
|
##### 2.缺页中断机构
|
|
|
|
|
|
发现访问的页面不在内存时,通知置换。
|
|
|
|
|
|
是特殊的一种中断,有如下不同:
|
|
|
|
|
|
+ CPU检测中断时间不同
|
|
|
+ 一般中断信号:一个指令周期为间隔
|
|
|
+ 缺页中断信号:执行期间可检测,更及时
|
|
|
+ CPU可多次处理
|
|
|
+ 一个指令周期多次检测到缺页中断,CPU都会及时处理
|
|
|
+ 处理过程需要软件和硬件同时完成
|
|
|
|
|
|
##### 3.地址变换机构
|
|
|
|
|
|
再程序运行过程中需要逐步将页面调入内存,在程序运行过程完成逻辑地址到物理地址的转换,是动态重定位装入。
|
|
|
|
|
|
![地址变换机构](http://47.117.160.245:8080/pictrue/private/os_09.png)
|
|
|
|
|
|
虚拟存储器管理是以牺牲系统开销为代价,换取内存的逻辑补充。
|
|
|
|
|
|
在具体实施时,需要解决如下策略问题:
|
|
|
|
|
|
+ 调页策略:何时将需要的页面调入内存
|
|
|
+ 分配策略:应该分配多少内存中的物理块
|
|
|
+ 内存置换策略:哪些页面被换出内存
|
|
|
|
|
|
##### 4.调页策略*
|
|
|
|
|
|
+ 请求页调入:在CPU访问进程页面时,请求将页面调入内存
|
|
|
|
|
|
优点:
|
|
|
|
|
|
+ 只有在需要时才将页面调入内存,节省了内存空间
|
|
|
|
|
|
缺点:
|
|
|
|
|
|
+ 初次执行时,大量页面调入内存
|
|
|
+ 缺页时仅调入一个,I/O频率高
|
|
|
+ 执行顺序跳跃性大的程序,缺页情况变化大,难以趋向稳定的水平,系统不稳定
|
|
|
|
|
|
+ 预先页调入:预先动态估计进程可能要访问的页面,并在访问前预先调入内存
|
|
|
|
|
|
优点:
|
|
|
|
|
|
+ 一次可调入多个页面,减少了中断、I/O次数
|
|
|
|
|
|
缺点:
|
|
|
|
|
|
+ 依赖估计准确率
|
|
|
+ 需要程序预先提供部分信息,否则调度策略难以实施
|
|
|
|
|
|
##### 5.分配策略*
|
|
|
|
|
|
物理块的分配策略:
|
|
|
|
|
|
+ 进程平均分配法
|
|
|
+ 进程按比例分配法
|
|
|
+ 进程优先权分配法
|
|
|
|
|
|
+ 进程的最小物理块数:无论如何,首要是保证进程的正常运行
|
|
|
|
|
|
##### 6.内存置换策略
|
|
|
|
|
|
全局置换、局部置换
|
|
|
|
|
|
+ 可变分配全局置换:先分配一定量的物理块,需要时首先考虑空闲物理块,其次从全部中选择置换
|
|
|
+ 固定分配局部置换:先分配一定数目,不改变,缺页时从当前进程的页面中置换
|
|
|
+ 可变分配局部置换:先分配一定数目,缺页自身置换,**频繁缺页时,系统在分配若干物理块**
|
|
|
|
|
|
#### 5.5.3 页面置换算法
|
|
|
|
|
|
设计问题:需要一个空闲页面时选择哪个页面来进行置换。
|
|
|
|
|
|
目标:减少缺页中断的次数,即减少缺页率
|
|
|
|
|
|
影响缺页率的因素:
|
|
|
|
|
|
+ 进程的内存物理块数
|
|
|
+ 页面大小
|
|
|
+ 程序的局部性
|
|
|
+ 页面置换算法
|
|
|
|
|
|
##### 1.最佳置换算法
|
|
|
|
|
|
+ 选择一个随后最长时间不会被访问的页面进行置换
|
|
|
+ 产生缺页中断次数最小
|
|
|
+ 要具备预知未来的能力
|
|
|
|
|
|
是理论上的算法,难以实现:预知未来很困难
|
|
|
|
|
|
##### 2.FIFO(First in, First out)算法
|
|
|
|
|
|
+ 更换最早进入内存的页面
|
|
|
+ 按照进入内存的次序维护一个所有页面的链表
|
|
|
+ 每次替换链表头部的页面
|
|
|
|
|
|
缺点:可能出现最先加载进来的页面是经常被访问的页面
|
|
|
|
|
|
##### 3.最近最久未使用(LRU)算法
|
|
|
|
|
|
+ 使用过去的数据预测未来
|
|
|
+ 如果一个页面长时间未被使用→可能之后很长一段时间也用不到
|
|
|
|
|
|
实现:矩阵/移位寄存器记录页面使用时间
|
|
|
|
|
|
##### 4.时钟算法
|
|
|
|
|
|
+ 每个页面常驻访问位,被访问时置1
|
|
|
+ 访问位可以被操作系统清零
|
|
|
+ 查找一个要被替换的页面时查看正在被指针指向的页面
|
|
|
+ 访问位为0则换出
|
|
|
+ 访问位为1则置0并指向下一位
|
|
|
|
|
|
##### 5.改进型时钟算法
|
|
|
|
|
|
+ 除考虑页面访问情况外,还需要考虑置换代价,即修改位
|
|
|
|
|
|
#### 5.5.4 页面调度性能*
|
|
|
|
|
|
虚拟存储器管理以时间换空间,是否值得要从缺页率、页面大小等方面分析。
|
|
|
|
|
|
缺页不仅会使缺页的进程运行减慢,也会影响其他进程的运行,因此分配物理块和选择置换算法需要慎重考虑。
|
|
|
|
|
|
对换空间的速度一般更快。
|
|
|
|
|
|
L=根号2nA为最佳页面长度
|
|
|
|
|
|
#### 5.5.5 请求分段存储、请求段页存储管理
|
|
|
|
|
|
将段放入外存,在执行时调入内存
|
|
|
|
|
|
---
|
|
|
|
|
|
# 第六章 设备管理
|
|
|
|
|
|
### 6.1 I/O系统
|
|
|
|
|
|
#### 6.1.1 I/O设备
|
|
|
|
|
|
I/O设备种类繁多,管理复杂,从OS角度看硬件,其性能指标有:设备使用特性、数据传输速率、数据的传输单位、设备共享属性等。
|
|
|
|
|
|
+ 按设备使用特性分类
|
|
|
+ 存储设备,外存或辅助存储器
|
|
|
+ 输入输出设备,包括输入设备、输出设备、交互式设备
|
|
|
+ 按传输速率分类
|
|
|
+ 低速设备:键盘、鼠标
|
|
|
+ 中速设备:打印机
|
|
|
+ 高速设备:磁带、磁盘、光盘
|
|
|
+ 按信息交换单位分类
|
|
|
+ 块设备,以数据块为单位存储和传输数据,数据块可寻址,如磁盘
|
|
|
+ 字符设备,以字符为单位存放传输设备,如交互式终端、打印机等
|
|
|
+ 按设备的共享属性分类
|
|
|
+ 独占设备,即临界资源
|
|
|
+ 共享设备,可寻址和随机访问的设备,如磁盘
|
|
|
+ 虚拟设备,通过虚拟技术把一台独占设备变换为若干台逻辑设备
|
|
|
+ 按设备从属关系分类
|
|
|
|
|
|
I/O设备的传输速率涵盖范围很宽,对用户需要隐藏这种差异
|
|
|
|
|
|
#### 6.1.2 设备控制器
|
|
|
|
|
|
> **设备控制器**是计算机中的一个实体
|
|
|
>
|
|
|
> + 控制一个或多个I/O设备
|
|
|
> + 实现设备和计算机之间的数据交换
|
|
|
> + 也成为适配器,是CPU和I/O设备间的一个接口
|
|
|
> + 通常是一块印刷电路板
|
|
|
|
|
|
功能:
|
|
|
|
|
|
+ 接受和识别CPU命令
|
|
|
+ 实现数据交换
|
|
|
+ 标识、报告设备状态
|
|
|
+ 识别设备地址
|
|
|
+ 数据缓冲
|
|
|
+ 差错控制
|
|
|
|
|
|
#### 6.1.3 I/O通道
|
|
|
|
|
|
> **通道**是一种特殊的执行I/O指令的处理机,用于代替处理器实现外部设备的输入/输出操作和管理,实现外部设备与处理器的并行操作。
|
|
|
|
|
|
引入目的:解脱CPU对I/O的组织和管理
|
|
|
|
|
|
通道类型:
|
|
|
|
|
|
+ 字节多路通道:以字节为单位,分时共享方式传输数据
|
|
|
+ 数组选择通道:每个子通道以一组数据为单位
|
|
|
+ 数组多路通道:结合了前两者优点,能分时并发,传输速率高
|
|
|
|
|
|
### 6.2 I/O控制方式
|
|
|
|
|
|
I/O控制的方式不断发展,以尽量减少主机对I/O控制的干预
|
|
|
|
|
|
+ 可编程I/O-最简单
|
|
|
+ 中断驱动I/O-最常用
|
|
|
+ 直接内存访问I/O-改进效率
|
|
|
+ I/O通道控制方式
|
|
|
|
|
|
##### 1.可编程I/O控制方式
|
|
|
|
|
|
+ CPU等待I/O完成
|
|
|
+ 这种模式称为轮询或繁忙等待
|
|
|
|
|
|
##### 2.中断驱动I/O
|
|
|
|
|
|
+ CPU初始化I/O
|
|
|
+ CPU去忙别的事情
|
|
|
+ I/O完成时,CPU将被中断
|
|
|
+ CPU处理中断
|
|
|
+ CPU恢复被中断的程序
|
|
|
|
|
|
##### 3.直接内存访问I/O
|
|
|
|
|
|
+ 中断驱动的明显缺陷是频繁的中断,以字节为单位
|
|
|
+ 解决方式是使用DMA(Direct Memory Access)
|
|
|
+ 数据传输的基本单位是块
|
|
|
+ 使用DMA控制器处理I/O中断
|
|
|
+ 降低CPU响应中断的频率
|
|
|
+ DMA控制器组成:
|
|
|
+ 主机与DMA控制器接口
|
|
|
+ DMA控制器与块设备接口
|
|
|
+ I/O控制逻辑
|
|
|
+ DMA控制器中设置四类寄存器
|
|
|
+ 命令/状态寄存器(CR)
|
|
|
+ 内存地址寄存器(MAR)
|
|
|
+ 数据寄存器(DR)
|
|
|
+ 数据计数器(DC)
|
|
|
|
|
|
##### 4.I/O通道控制方式
|
|
|
|
|
|
引入:
|
|
|
|
|
|
+ DMA对许多离散块的读取仍需多次中断
|
|
|
+ 进一步减少CPU的干预,把对一个数据块的读写干预减少为一组数据块的读写干预
|
|
|
|
|
|
在I/O通道控制方式中,CPU只需给出:
|
|
|
|
|
|
+ 通道程序首址
|
|
|
+ 要访问的I/O设备
|
|
|
|
|
|
### 6.3 缓冲管理
|
|
|
|
|
|
> **缓冲**是在通信问题中,为了使通信双方的速度得到匹配而引入的一个中间层次。这个层次比通信中较慢的一方快,而与较快的一方更加匹配。
|
|
|
|
|
|
引入:
|
|
|
|
|
|
+ 缓和CPU与I/O设备速度不匹配的矛盾
|
|
|
+ 减少对CPU的中断频率
|
|
|
+ 提高CPU和I/O设备间的并行性
|
|
|
+ 协调传输数据大小不一致的设备
|
|
|
|
|
|
若没有缓冲区:
|
|
|
|
|
|
+ 磁盘把一块数据送入用户区,花费时间为T
|
|
|
+ CPU对数据进行计算,花费时间为C
|
|
|
|
|
|
系统对整块数据的处理时间为`T+C`
|
|
|
|
|
|
问题:通常T>C,CPU等待
|
|
|
|
|
|
提供缓冲区:
|
|
|
|
|
|
+ 磁盘把一块数据送入缓冲区,花费时间T
|
|
|
+ 缓冲区数据送入用户区,花费时间M
|
|
|
+ CPU进行计算,花费时间C
|
|
|
|
|
|
系统对整块数据处理时间为`max(C,T)+M`
|
|
|
|
|
|
双缓冲:
|
|
|
|
|
|
+ 先将数据送到第一个缓冲区
|
|
|
+ 向第二个缓冲区输送数据同时,CPU计算
|
|
|
+ 系统处理一块数据时间为`max(C,T)`
|
|
|
|
|
|
循环缓冲:类似生产者-消费者问题。
|
|
|
|
|
|
### 6.4 I/O软件
|
|
|
|
|
|
I/O软件是实现I/O管理的软件部分,I/O软件设计目标是改善I/O设备的效率,实现统一标准的I/O设备管理方式。
|
|
|
|
|
|
I/O软件的目标:
|
|
|
|
|
|
+ 设备独立
|
|
|
+ 统一命名
|
|
|
+ 错误处理
|
|
|
+ 缓冲技术
|
|
|
+ 设备的分配和释放
|
|
|
|
|
|
I/O软件普遍采用层次式结构
|
|
|
|
|
|
+ 低层次实现与硬件相关操作,并屏蔽硬件的具体细节
|
|
|
+ 高层次向用户提供一个简洁、统一的接口
|
|
|
+ 每一层具有一个要执行的定义明确的功能和一个与近邻层次定义明确的接口
|
|
|
+ 不同操作系统的分层是不同的
|
|
|
|
|
|
![层次式I/O软件](http://47.117.160.245:8080/pictrue/private/os_10.png)
|
|
|
|
|
|
+ 中断处理过程:大多I/O是中断驱动
|
|
|
+ 设备驱动程序
|
|
|
+ 接受由独立软件发来的命令和参数
|
|
|
+ 检查I/O
|
|
|
+ 对等待I/O的进程排队
|
|
|
+ 及时响应由控制器和通道发来的中断请求
|
|
|
+ 设备独立I/O软件
|
|
|
+ 设备独立是OS的一个重要概念
|
|
|
+ 引入逻辑设备和物理设备
|
|
|
|
|
|
### 6.5 设备分配
|
|
|
|
|
|
引入:系统设备供所有进程共享,为了防止进程对系统资源的无序使用,必须由系统统一进行设备分配。
|
|
|
|
|
|
包括:设备、控制器和通道
|
|
|
|
|
|
设备分配用数据结构:
|
|
|
|
|
|
+ 设备控制表DCT
|
|
|
+ 控制器控制表COCT
|
|
|
+ 通道控制表CHCT
|
|
|
+ 系统设备表SDT
|
|
|
|
|
|
![引入挂起的状态转换](http://47.117.160.245:8080/pictrue/private/os_11.png)
|
|
|
|
|
|
![引入挂起的状态转换](http://47.117.160.245:8080/pictrue/private/os_12.png)
|
|
|
|
|
|
### 6.6 磁盘管理
|
|
|
|
|
|
> 磁盘存储器是计算机中重要的输入/输出设备,是除内存外最重要的计算机存储器,其优点表现在以下方面:
|
|
|
>
|
|
|
> + 存储容量大
|
|
|
> + 价格低
|
|
|
> + 断电后信息不丢失
|
|
|
|
|
|
磁盘管理的主要任务:
|
|
|
|
|
|
+ 分配存储空间
|
|
|
+ 组织存取方式
|
|
|
+ 提高存储空间利用率
|
|
|
+ 提高对磁盘的I/O速度
|
|
|
+ 采取必要的冗余措施保证文件系统的可靠
|
|
|
|
|
|
#### 6.6.1 磁盘性能
|
|
|
|
|
|
##### 1.磁盘结构
|
|
|
|
|
|
+ 磁盘由一组旋转的盘面组成
|
|
|
+ 每个盘面的**上下**表面有一个个的同心圆
|
|
|
+ 称为磁道
|
|
|
+ 具有相同半径的磁道称为磁柱
|
|
|
+ 每个磁道被进一步划分为扇区
|
|
|
+ 扇区是磁盘I/O的基本单位
|
|
|
+ 扇区可以是连续的(逻辑临近=物理临近)或是交错的(逻辑临近!=物理邻近)
|
|
|
+ 磁盘读写过程
|
|
|
+ 将磁头移动到正确的磁道-寻道
|
|
|
+ 等待磁头到达所在删去-旋转
|
|
|
+ 读写数据-数据传输
|
|
|
|
|
|
##### 2.寻道时间
|
|
|
|
|
|
+ 读写磁头移动到所要求的磁道位置的平均时间——依赖于磁头和磁道的距离
|
|
|
+ 磁道到磁道的访问时间——磁头移动到相邻磁道所需时间
|
|
|
+ 平均寻道时间——随机存取中到达要求磁道的平均时间
|
|
|
|
|
|
##### 3.旋转延迟和传输时间
|
|
|
|
|
|
+ 旋转延迟/等待时间:到达磁道后等待要求扇区转到磁头下方的平均时间
|
|
|
+ 通常是旋转时间的一半:对于7200RPM的磁盘,旋转一周时间为1min/7200转=60000ms/7200转=8.3ms,则旋转延迟约为4.2ms
|
|
|
+ 传输时间:数据从磁盘读出或者向磁盘写入数据需要的时间
|
|
|
+ 爆发速度:磁盘到达扇面后磁盘驱动器输出或接受数据的最大速度
|
|
|
|
|
|
计算:
|
|
|
|
|
|
平均访问时间=寻道时间+旋转延迟
|
|
|
|
|
|
爆发传输速度=每秒旋转次数\*每次旋转经过扇面数\*每个扇面的字节数
|
|
|
|
|
|
顺序访问只需寻道一次,之后每个磁道的读取不需寻道,只需计算旋转延迟
|
|
|
|
|
|
随机访问每次访问一个扇区都要计算寻道时间+旋转延迟+读取一个扇区的时间
|
|
|
|
|
|
#### 6.6.2 磁盘调度
|
|
|
|
|
|
准则为进程对磁盘的平均访问时间最小
|
|
|
|
|
|
+ 先来先服务(FCFS):根据进程访问磁盘的先后顺序
|
|
|
+ 平均访问时间较长
|
|
|
+ 最短寻道时间(SSTF):选择要访问的磁道与当前所在磁道最近的进程
|
|
|
+ 造成饥饿
|
|
|
+ 扫描(SCAN)算法:在选择时选择与磁头移动方向相同且最近的进程
|
|
|
+ 缓解了饥饿现象
|
|
|
+ 循环扫描(CSCAN)算法:磁头总是按一个方向单向移动
|
|
|
+ 磁臂黏着
|
|
|
+ NStepSCAN:按FCFS分配队列,在处理队列时使用SCAN算法
|
|
|
|
|
|
---
|
|
|
|
|
|
# 第七章 文件系统
|