发展阶段 | 存在问题或特点 | 特性 |
---|---|---|
手工操作阶段 | 人机速度矛盾 | |
单道批处理系统 | 资源利用率低 | 自动性、顺序性、单道性 |
多道批处理系统 | 没有人机交互 | 资源利用率高、系统吞吐量大、平均周转时间长、无交互能力 |
分时OS | 没有优先级 | 多路/同时性(主机同时连接多个终端) 独立性(用户终端彼此不干扰) 及时性(及时响应用户请求) 交互性 |
硬实时OS | 严格规定时间内完成 | 多路性、独立性、及时性、交互性、可靠性 |
软实时OS | 可偶尔违反时间规定 | 多路性、独立性、及时性、交互性、可靠性 |
微机操作系统 | 单用户单任务、单用户多任务、多用户多任务 | |
分布式操作系统 |
状态 | PSW | 程序 | 指令 |
---|---|---|---|
核心态/管态 | 1 | 内核程序 | 全部指令(特权、非特权) |
用户态/目态 | 0 | 应用程序 | 非特权指令 |
用户态可以发生:系统调用、中断(外部中断、缺页等),但不能发生进程切换。
系统调用需要执行一些特权指令,故需要在核心态下进行。
系统调用是操作系统与程序之间的接口。
系统调用和库函数:系统调用需要使用汇编语言调用。高级语言库函数可以是对系统调用的封装(即库函数不一定使用到系统调用)。
操作系统主要功能(系统调用功能):处理机管理(进程控制、进程同步、进程通信、进程调度)、存储器管理/内存管理、设备管理、文件管理。
操作系统是层次且模块化的。
分类:无结构、模块化结构、分层式结构、微内核结构(小内核、C/S模式、机制与策略分离、面向对象技术)。
原语:由若干条指令组成的程序段,用来实现某个特定功能,在执行过程中不可被中断,由关中断和开中断来实现。
用户 | ||||||||||||||||||||||||||||||||||
应用程序 | ||||||||||||||||||||||||||||||||||
操作系统 | 非内核功能 | |||||||||||||||||||||||||||||||||
大内核 | 资源管理(进程管理、存储器管理、设备管理等) | |||||||||||||||||||||||||||||||||
微内核 | 时钟 | 中断 | 原语(设备驱动、CPU切换) | |||||||||||||||||||||||||||||||
裸机等 | ||||||||||||||||||||||||||||||||||
内核类型 | 优点 | 缺点 |
---|---|---|
大内核 | 高性能 | 内核代码庞大,结构混乱,难以维护 |
微内核 | 结构清晰,方便维护 | 性能低 |
程序(Program):是指令的有序集合(静态概念)。
进程(Process):进程实体(PCB)的运行过程(动态概念),是系统进行资源分配和调度的独立单位。一个进程可以执行多个程序。
作业(Job):起源于批处理系统,用户在一次计算过程中或者事务处理过程中,要求计算机所作工作的集合。一个作业可由多个进程组成。
顺序执行的程序具有:顺序性、封闭性、可再现性
并发执行的程序具有:间断性、无封闭性、不可再现性。
进程的特征:
进程实体:
PCB(Process Control Block):常驻内存,,创建进程就是创建进程实体中的PCB。撤销进程就是撤销进程实体中的PCB。
没有引入线程时,传统的进程是程序执行流的最小单位。引入线程后,进程是资源分配的基本单位;线程是调度的基本单位。同一进程的线程间并发不需要切换进程的运行环境,所以开销更小。
线程特点:轻型实体、独立调度和分配基本单位、可并发、共享进程资源。
用户级线程(协程) | 内核级线程 | |
---|---|---|
维护者 | 应用程序 | 操作系统内核 |
线程切换态 | 用户态 | 核心态 |
操作系统可见性 | 不可见 | 可见 |
等效实际调度数 | 否 | 是 |
管理开销 | 小 | 较大 |
用户线程与内核级线程 | 优点 | 缺点 |
---|---|---|
多对一 | 线程管理开销小 | 并发不高 |
一对一 | 并发高 | 线程管理成本高 |
多对多 |
进程互斥:对临界资源的访问,需要互斥进行。即当一个进程进入临界区使用临界资源时,另一个进程必须等待。
访问临界资源原则:空闲让进、忙则等待、有限等待、让权等待
进程同步:保证各个进程按预期的方式推进。
单标致法、双标志先检查法、双标志后检查法、Peterson算法
/** * 【单标致法】 * 说明:每个进程进入临界区的权限只能被另一个进程赋予。 * 问题:不遵循空闲让进。 */ int turn = 0; // P0 while(0 != turn) { // 进入区 ...; // 临界区 turn = 1; // 退出区 ...; // 剩余区 } // P1 while(1 != turn) { // 进入区 ...; // 临界区 turn = 0; // 退出区 ...; // 剩余区 }
/** * 【双标志先检查法】 * 说明:先检查后上锁,标记每个进程想进入临界区的意愿。 * 问题:不遵循忙则等待,若按①⑥②⑦③⑧顺序,则两者同时访问临界区。 */ bool flag[2]; flag[0] = false; flag[1] = false; // P0 while(flag[1]) { // ①进入区,其它进程是否想进入 flag[0] = true; // ②进入区,表明自己意愿 ...; // ③临界区 flag[0] = false; // ④退出区 ...; // ⑤剩余区 } // P1 while(flag[0]) { // ⑥进入区,其它进程是否想进入 flag[1] = true; // ⑦进入区,表明自己意愿 ...; // ⑧临界区 flag[1] = false; // ⑨退出区 ...; // ⑩剩余区 }
/** * 【双标志后检查法】 * 说明:先上锁后检查。 * 问题:不遵循空闲让进和有限等待,若按①⑥②⑦顺序,则两者均无法访问临界区。 */ bool flag[2]; flag[0] = false; flag[1] = false; // P0 flag[0] = true; // ①进入区,表明自己意愿 while(flag[1]) { // ②进入区,其它进程是否想进入 ...; // ③临界区 flag[0] = false; // ④退出区 ...; // ⑤剩余区 } // P1 flag[1] = true; // ⑥进入区,表明自己意愿 while(flag[0]) { // ⑦进入区,其它进程是否想进入 ...; // ⑧临界区 flag[1] = false; // ⑨退出区 ...; // ⑩剩余区 }
/** * 【Peterson算法】 * 说明:主动谦让。 * 问题:不遵循让权等待。 */ bool flag[2]; flag[0] = false; flag[1] = false; int turn = 0; // P0 flag[0] = true; // ①进入区,表明自己意愿 turn = 1 // ②进入区,主动避让 while(flag[1] && 1 == turn) { // ③进入区,其它进程是否想进入且当前礼让中 ...; // ④临界区 flag[0] = false; // ⑤退出区 ...; // ⑥剩余区 } // P1 flag[1] = true; // ⑦进入区,表明自己意愿 turn = 0 // ⑧进入区,主动避让 while(flag[0] && 0 == turn) { // ⑨进入区,其它进程是否想进入且当前礼让中 ...; // ⑩临界区 flag[1] = false; // ⑪退出区 ...; // ⑫剩余区 }
实现方式 | 优点 | 缺点 | |
---|---|---|---|
中断屏蔽 | 开/关中断指令 | 简单高效 | 只适用于单机处理 |
TestAndSet | 记录、上锁、检查 | 实现简单,多机适用 | 不遵循让权等待 |
Swap | 记录、上锁、检查 | 实现简单,多机适用 | 不遵循让权等待 |
软件和硬件互斥方法存在问题:
1.检查和上锁操作无法一气呵成。
2.无法实现让权等待。
原语:由关中断/开中断实现,一旦开始执行,就不能被中断的若干条指令。
PV操作:一对原语,wait(S)
和signal(S)
简称P(S)
、V(S)
,是一对低级进程通信原语。
整型信号量:
int S = 1; // 初始化整型信号量 void wait(int S) { while(S <= 0); // 资源不够则等待资源 S--; } void signal(int S) { S++; }
// P0进程 wait(S); // 申请资源S ...; // 使用资源S signal(S); // 释放资源S
记录型信号量:为解决整型信号量的忙等待问题,即不满足让权等待问题。
typedef struct { int value; // 可用资源数量 struct process *L; // 等待进程队列 } semaphore; void wait(semaphore S) { S.value--; if(S < 0) block(S.L); // RUNNING --> BLOCKED } void signal(semaphore S) { S.value++; if(S.value <= 0) wakeup(S.L) // BLOCKED --> READY }
// P0进程 wait(S); // 申请资源S ...; // 使用资源S signal(S); // 释放资源S
例1:有个进程并发,每个进程需要()个资源,问至少有多少资源不会发生死锁。
每个进程差个资源可以运行,再补充一台使至少有台不会无限等待则有:
例2:有可用资源,每个进程需要使用()个资源,问至多有几个线程不会发生死锁。
例3:有个程序共享同一程序段,每次最多允许个进程进入该程序短,问信号量取值范围
用于解决信号量机制编程复杂的问题,包含共享数据结构、数据结构初始化语句、一组用来访问数据结构的过程。
挂起:暂时被淘汰出内存的进程。
调度算法准则:面向用户准则(周转时间短、响应时间快、截止时间保证、优先权准则)、面向系统准则(吞吐量高、处理机利用率高、各资源的平衡利用)
进程调度时机:主动放弃(异常、IO操作)、被动放弃(时间片耗尽、高优先进程进入就绪队列)
进程调度方式:非抢占式调度算法(非抢占式轮换调度算法、非抢占式优先调度算法)、抢占式调度算法(基于时钟中断的抢占式优先权调度算法、立即抢占的优先级调度算法)
非剥夺调度方式(只允许主动放弃)、剥夺调度方式(抢占式)
调度层次 | 方向 | 发生频率 | 状态变化 | |
---|---|---|---|---|
高级调度/作业调度 | 外存→内存 | 最低 | 无→创建态→就绪态 | 将外存后备队列作业加入内存 |
中级调度/内存调度 | 外存→内存 | 中等 | 挂起态→就绪态 | 将挂起进程数据调回内存 |
低级调度/进程调度 | 内存→CPU | 最高 | 就绪态→运行态 | 为就绪队列分配处理机 |
作业调度工作:检查资源要求、分配内存调入作业、进程载入就绪队列。
算法 | 是否抢占 | 可能饥饿 | 特点 |
---|---|---|---|
FCFS(先来先服务) | 否 | 否 | 不利于短作业 |
SJF(短作业优先) | 均可 | 是 | 对长作业不利,平均等待时间最小 |
高优先权优先 | 均可 | 是 | 静态优先权 |
HRRN(高响应比优先) | 否 | 否 | 动态优先权,兼顾长/短作业 |
时间片轮换 | 是 | 否 | 频繁进程切换的开销大 |
多级反馈队列 | 是 | 是 | 目前效果最好 |
产生原因:竞争资源、请求和释放资源的顺序不当
产生必要条件:互斥访问、请求和保持(等待)、不可抢占、环路等待
硬件结构:寄存器、高速缓存、内存
内存保护:上下限寄存器、限长寄存器(届地址寄存器、重定位寄存器)
覆盖技术:按照逻辑,让不能同时被访问的程序段共享同一个覆盖区。
交换技术:内存紧张时,将内存中某些进程暂时换出到外存交换区(PCB则常驻内存)。
内存碎片:不能被使用的内存区域。
装入方式 | 可装入内存中不同位置 | 可在内存中移动 | 说明 |
---|---|---|---|
绝对装入 | × | × | 程序中的逻辑地址即为物理地址 |
可重定位装入 | √ | × | 装入时将逻辑地址转换为物理地址 |
动态运行时装入 | √ | √ | 运行时将逻辑地址转换为物理地址 需设置重定位寄存器 |
实现方法 | 有外部碎片 | 有内部碎片 | |
---|---|---|---|
单一连续分配 | 直接分为系统区和用户区 | × | √ |
固定分区分配 | 用户区分为固定大小的多个子分区 | × | √ |
动态分区分配 | 装入时基于程序大小动态创建 | √ | × |
动态可重定位分配 | 空间不够时整理分散的小分区为一个大分区 | √ | × |
动态分区分配算法:需要能描述空闲分区和已分配分区的数据结构,常用数据结构有空闲分区表、空闲链表。若分区回收后与前后分区均为空闲分区,则应将其合并存储。
动态分区分配算法 | 思想 | 空闲分区 | 开销 | 大作业 | 特点 |
---|---|---|---|---|---|
首次适应 | 从头到尾找最适 | 地址递增 | 小 | 有利 | 优先使用低地址 |
邻近/循环首次 | 从上次结束开始 | 地址递增 | 小 | 不利 | 高低地址使用均匀 |
最佳适应 | 优先使用小分区 | 容量递增 | 大 | 有利 | 许多难以利用小空间 |
最坏适应 | 优先使用大分区 | 容量递减 | 大 | 不利 | 产生碎片概率低 |
快速适应 | 分区按容量分类 | 分类存放 | 大 | 有利 | 多个空闲分区链表 |
基本思想:非连续分配,把进程分页,各个页面离散的放到各个内存块中。
物理层面:将内存空间分为多个大小相等(太大可能产生过大的内部碎片)的分区,每个分区就是一个页框(页帧、内存块、物理块),每个页框有一个编号即页框号(页帧号、内存块号、物理块号),页框号从0开始。
逻辑层面:用户进程的地址空间也分为与页框大小相等的一个个区域称为页(页面),每个页有一个页号,页号从0开始。
页表:存储了逻辑页与物理块的对应关系(页号, 块号)
。故CPU每次读取数据都需要次访存,第一次访问内存中的页表,第二次通过查询页表获得的物理地址访问内存获得所需数据。
页表长度:页表有几个页表项(多少行)。
页表项长度:页表项占存储空间大小(一行大小)。
页面长度:页面占存储空间大小。
快表:当页表项缓存于寄存器时,即为快表。此时每次读取数据仅需次访存。
多级页表:各级页表大小不能超过一个页面大小,使用两级页表((一级页号, 二级页号, 页内偏移量)
、(页号, 块号)
)需要次访存,级页表需要次访存。
地址转换
例:页面长度=1KB = 0x400
,页表如下,问逻辑地址0A1F(H)
对应的物理地址
页号 | 块号 |
---|---|
0 | 1 |
1 | 5 |
2 | 3 |
3 | 7 |
4 | 2 |
0x0A1F = 2 × 0x400 + 0x21F
,即页号为2
(块号为3
),页面偏移量为0x21F
。3 × 0x400 + 0x21F = 0xE1F
分段 | 分页 | |
---|---|---|
信息单位 | 信息的物理单位 | 信息的逻辑单位 |
目的 | 提高内存利用率 | 更好地满足用户需要 |
用户可见性 | 不可见 | 可见 |
大小 | 由系统决定的固定大小 | 取决于用户编译时信息的性质 |
维度 | 一维(逻辑地址) | 二维(段名,段内地址) |
段表:存储了逻辑段与物理地址的对应关系(段号(隐含), 段长, 基址)
。
先将程序分为若干段,再将每段分为若干页。逻辑地址结构为用户提供(段号, 段内地址)
,实际存储(段号, 页号, 页内偏移量)
。段页式段表为(段号(隐含), 页表长度, 页表存放地址)
与分段存储管理中的段表不同。段页式访问一个逻辑地址需要访存次(段表->
页表->
物理地址),若快表命中则仅需次访存。
从逻辑上扩充内存容量,程序不需要全部装入内存即可允许,运行时根据需要动态调入数据,内存不够时换出一部分数据。
虚拟内存的最大容量:由系统的地址结构和外存空间大小决定。
虚拟内存组成:主存、辅存、管理单元、管理软件。
调入策略:预调页策略、请求调页策略
局部性原理:
虚拟内存特征:
实现技术:
(页号, 块号, 状态位, 访问字段, 修改位, 外存地址)
优先淘汰 | 性能 | 特点 | |
---|---|---|---|
最佳置换算法(OPT) | 最长时间不被访问的页面 | 最好 | 缺页率最小,但无法实现 |
先进先出(FIFO) | 最先进入内存的页面 | 很差 | 实现简单,可能出现Belady异常 |
最近最久未使用(LRU) | 最近最久没有访问的页面 | 好 | 算法开销大,需硬件支持 |
CLOCK/NRU | 第一个访问位为0的 | 好 | 实现简单,开销小 |
最少使用(LFU) | |||
页面缓冲(PBA) |
CLOCK/NRU算法:采用循环队列构建页面队列,记录(访问位)
,访问后若为1则置为0,最多2轮即可找到要淘汰的页。
改进的CLOCK/NRU算法:增加了置换代价因素,记录(访问位, 修改位)
,最多进行4轮扫描即可找到要淘汰的页。
(0,0)
(0,1)
,所有扫描过的访问位=0
(0,0)
(0,1)
驻留集:请求分页存储管理中给进程分配的物理块的集合。
工作集:某段时间间隔内,进程实际访问的页面的集合。
固定分配/可变分配:运行期间驻留集大小是否可变。
局部替换/全局替换:缺页时,是否只能换出进程自己的页面。
抖动:刚换入的页面马上又要换出,主要原因是进程频繁访问的页面数目高于可用物理块数,即分配给进程的物理块不够。
设备IO方式:轮询、中断、直接访存、通道控制
作业IO方式:联机、脱机、假脱机
缓冲区管理:
层次结构:
按设备使用分类:存储设备、输入输出设备
按设备速率分类:低速、中速、高速
按设备交换单位分类:块设备(传输快,可寻址)、字符设备(传输慢,不可寻址,常采用中断驱动方式)
按设备共享属性分类:独占设备、共享设备、虚拟设备
功能:接受和识别CPU发出的命令、向CPU报告设备状态、数据交换、地址识别
组成:CPU与控制器接口、IO逻辑、控制器与设备之间的接口
寄存器编址方式:内存映射I/O、寄存器独立编址
过程 | CPU干预频率 | 数据传输单位 | 数据流向 | |
---|---|---|---|---|
程序直接控制方式 | CPU发出I/O命令后需要不断轮询 | 极高 | 字 | 设备→CPU→内存; 内存→CPU→设备 |
中断驱动方式 | CPU发出I/O命令后可以做其他事, 本次I/O完成后设备控制器发出中断信号 |
高 | 字 | 设备→CPU→内存; 内存→CPU→设备 |
DMA方式 | CPU发出命令后可以做其他事, 本次I/O完成后DMA控制器发出中断信号 |
中 | 块 | 设备→内存; 内存→设备 |
通道控制方式 | CPU发出I/O命令后可以做其他事, 通道会执行通道程序以完成I/O, 完成后通道向CPU发出中断信号 |
低 | 一组块 | 设备→内存; 内存→设备 |
相关数据结构:设备控制表(DCT)、控制器控制表(COCT)、通道控制表(CHCT)、系统涉笔表(SDT)。
分配时考虑因素:设备固有属性(独占性、共享性、可虚拟性)、设备分配算法、分配中安全性。
设备分配步骤:用户编程时使用逻辑设备名,OS通过物理设备名映射表(LUT)实现从逻辑设备名到物理设备名的映射。
SPOOLing:提高IO速度、独占设备改造为共享设备、实现了虚拟设备功能。是一种以空间换时间的技术。
算法 | 说明 |
---|---|
先来先服务(FCFS) | |
最短寻找时间优先(SSTF) | 仅能保证眼前最优,无法保证总体最优,且可能导致饥饿 |
扫描算法(SCAN) | 磁头移动到最边缘的磁道时才可改变磁头移动方向 |
LOOK | 磁头移动方向上不再有请求,就立即改变磁头移动方向 |
循环扫描(C-SCAN) | 磁头朝某方向移动时才会响应请求,移动到边缘后立即让磁头折回起点 |
C-LOOK | 只有在磁头移动方向上不再有请求,就立即让磁头返回 |
(柱面号, 盘面号, 扇区号)
结构以减少移动磁头次数RAID等级 | 速度 | 容错 | 可用容量 | 磁盘数 | 说明 |
---|---|---|---|---|---|
RAID-0 | ↑↑ | × | 双区域并行交叉存取 | ||
RAID-1 | - | √ | 提供磁盘镜像功能 | ||
RAID-5 | ↑ | √ | 分布奇偶校验条带 |
STF-Ⅰ
:双份目录双份文件、写后读校验STF-Ⅱ
:磁盘镜像、磁盘双工STF-Ⅲ
:双机热备、双机互备、公用磁盘文件系统:由文件管理有关软件、被管理文件、实施管理所需的数据结构等组成。
文件数据:
数据项
:字母或数字等基本数据单位文件属性
:文件类型、长度、位置、建立时间等附加信息记录 = 数据项的集合
文件 = 记录 + 文件属性
文件共享方式:
文件保护方式:
文件系统层次结构:
主要解决如何为新文件分配存储空间的问题。
文件存储空间划分:逻辑卷/文件卷、目录区(文件目录、空闲表、位示图、超级块)、文件区
管理方法 | 特点 |
---|---|
空闲表法 | 连续分配方式 |
空闲盘块链 | 以盘块为单位组成一条空闲链 |
空闲盘区链 | 以盘区为单位组成一条空闲链 |
位示图法 | 每个盘块对应一个二进制位 |
成组链表法 | 空闲盘块分组成链,UNIX采用,适合大型文件系统 |
有结构文件由记录组成,又称记录式文件,记录分为定长记录和可变长记录。
(索引号, 长度, 指针)
,索引表本身是定长记录的顺序文件文件目录:一个文件对应一个FCB、一个FCB就是一个目录项,多个FCB组成文件目录。
索引结点:除文件名之外所有信息都放到索引节点中,每个文件对应一个索引结点。
目录查询方法:线性检索、Hash方法
目录结构:
包括:顺序结构、链式结构、索引结构。
实现 | 目录 | 优点 | 缺点 | |
---|---|---|---|---|
连续分配 | 文件在磁盘占有连续的块 | 起始块号 ,文件长度 |
支持随机访问, 顺序存取速度快 |
会产生碎片,不方便扩展 |
隐式链接 | 块中包含指向下一块的指针 | 起始块号 ,结束始块号 |
方便扩展, 不会有碎片,外存利用率高 |
只支持顺序访问 |
显式链接 | 文件分配表FAT记录了 物理块指针并常驻内存 |
起始块号 |
支持随机访问, 方便扩展, 不会有碎片,外存利用率高 |
FAT会占用内存空间 |
链接索引 | 索引表链接存放 | 第一个索引块块号 |
支持随机访问, 方便扩展 |
大文件索引表很长 |
多层索引 | 一级索引表指向二级索引表… | 顶层索引块块号 |
支持随机访问, 方便扩展 |
小文件也要多次访问磁盘找到下级索引表 |
混合索引 | 索引表既存放物理块指针 也存放下一级索引表 |
顶层索引块块号 |
支持随机访问, 方便扩展, 小文件访磁盘次数更少 |