diff --git a/Office/excel/说明.md b/Office/excel/说明.md
new file mode 100644
index 00000000..b1681536
--- /dev/null
+++ b/Office/excel/说明.md
@@ -0,0 +1,2 @@
+1. 多级列表表示文字层级
+2. 图形,可以表示递进关系
\ No newline at end of file
diff --git a/Office/word/说明.md b/Office/word/说明.md
new file mode 100644
index 00000000..b1681536
--- /dev/null
+++ b/Office/word/说明.md
@@ -0,0 +1,2 @@
+1. 多级列表表示文字层级
+2. 图形,可以表示递进关系
\ No newline at end of file
diff --git a/工作日志/2021年2月27日-三月份计划.md b/工作日志/2021年2月27日-三月份计划.md
index 629ef310..2b936c37 100644
--- a/工作日志/2021年2月27日-三月份计划.md
+++ b/工作日志/2021年2月27日-三月份计划.md
@@ -22,9 +22,15 @@
- [ ] 标准库(网络编程、多,周)
- 数据结构
- [ ] 《大话数据结构》
- - 算法
- [ ] 《数据结构与算法分析》
- [ ] 《算法图解》
+ - 算法
+ - [x] 学习、复习枚举法
+ - [ ] 学习、复习分治法(把相关思想下的问题和算法补充完整)
+ - [ ] 学习、复习动态规划
+ - [ ] 学习、复习贪心
+ - [ ] 学习、复习回溯剪枝
+ - [ ] 学习、复习分支限界
- 知识复习——基础(一周)
- [ ] 计算机网络
- [ ] 数据库
diff --git a/工作日志/2021年3月17日-今日计划.md b/工作日志/2021年3月17日-今日计划.md
index 2f3013ba..d2f8d4e2 100644
--- a/工作日志/2021年3月17日-今日计划.md
+++ b/工作日志/2021年3月17日-今日计划.md
@@ -1,11 +1,7 @@
# 计划
- [x] 对刷题的内容进行总结。首先进行这个总结。(一半了)
- [x] 实现字符串分割和字符串格式化的方法(C++库string篇)
-- [ ] 学习、复习分治法(把相关思想下的问题和算法补充完整)
-- [ ] 学习、复习动态规划
-- [ ] 学习、复习贪心
-- [ ] 学习、复习回溯剪枝
-- [ ] 学习、复习分支限界
+- [x] 学习、复习枚举法
- [x] 学习C++容器。对容器的构造函数进行总结。
- [x] 学习C++容器。对每个容器的基础操作进行总结。
- [x] 学习C++模板算法。对算法的第三个参数进行总结。
diff --git a/工作日志/2021年3月24日-今日计划.md b/工作日志/2021年3月24日-今日计划.md
index 1270316e..ab4d50c1 100644
--- a/工作日志/2021年3月24日-今日计划.md
+++ b/工作日志/2021年3月24日-今日计划.md
@@ -1,8 +1,8 @@
## 计划
- [x] pytorch动态数据分类
-- [ ] sklearn静态数据分类
-- [ ] pytorch静态数据分类
+- [x] sklearn静态数据分类
+- [x] pytorch静态数据分类
## 收获
\ No newline at end of file
diff --git a/工作日志/2021年3月27日-今日计划.md b/工作日志/2021年3月27日-今日计划.md
index 8041f1b6..838b69f7 100644
--- a/工作日志/2021年3月27日-今日计划.md
+++ b/工作日志/2021年3月27日-今日计划.md
@@ -5,14 +5,19 @@
- [x] 字符串分割与格式化方法总结
- [x] 位运算与补码总结
- [x] 大数运算
-- [ ] n个骰子的点数
-- [ ] 约瑟夫问题
-- [ ] 手写所有排序
-
+- [x] n个骰子的点数
+- [x] 约瑟夫问题
+- [x] 手写所有排序
## 收获
-
+* LeetCode的笔记终于整理完了。对各类算法题有了初步的认识。接下来数据结构与算法。主要整理各个算法思想下的典型问题。结合本科时候的笔记。彻底整理完成小尾巴。
+* 基础知识的复习要开始了。感觉已经满了很多。不仅仅有基础知识。
+* 还有自己的项目经历的整理。应该整理一份三到四个项目经历的说明文档。用到了那些技术。你在其中主要做了什么事情。
+* 联邦学习和恶意软件的进度。每天都要推进一些。至少应该在本周把基础框架和应用方法整理完成。
+
+
+* 相当于现在同时上:数据结构与算法、计算机网络、数据库、操作系统、机器学习。五门超级大的课程。确实很有挑战。加油吧。少年。清明节能回家吗?堪忧啊。生活总是这么让人头秃。。。
diff --git a/工作日志/2021年3月29日-今日计划.md b/工作日志/2021年3月29日-今日计划.md
new file mode 100644
index 00000000..06a91342
--- /dev/null
+++ b/工作日志/2021年3月29日-今日计划.md
@@ -0,0 +1,8 @@
+## 计划
+> 每日计划包括三方面的内容:数据结构与算法、基础知识与项目经历、联邦学习与恶意软件
+
+- [x] 数据结构预算法——蛮力法整理完成
+- [ ] 基础知识与项目经历——操作系统整理开始part1
+- [ ] 联邦学习与恶意软件——pysyft学习完成
+
+## 收获
\ No newline at end of file
diff --git a/工作日志/2021年3月30日-今日计划.md b/工作日志/2021年3月30日-今日计划.md
new file mode 100644
index 00000000..e14ff2d6
--- /dev/null
+++ b/工作日志/2021年3月30日-今日计划.md
@@ -0,0 +1,10 @@
+## 计划
+
+> 每日计划包括三方面的内容:数据结构与算法、基础知识与项目经历、联邦学习与恶意软件
+
+- [ ] 数据结构预算法——分治法整理完成
+- [ ] 基础知识与项目经历——操作系统整理完成part2
+- [ ] 联邦学习与恶意软件——TensorFlow学习开始part1
+
+
+## 收获
\ No newline at end of file
diff --git a/工作日志/2021年3月31日-今日计划.md b/工作日志/2021年3月31日-今日计划.md
new file mode 100644
index 00000000..9cbdc2f8
--- /dev/null
+++ b/工作日志/2021年3月31日-今日计划.md
@@ -0,0 +1,9 @@
+## 计划
+
+> 每日计划包括三方面的内容:数据结构与算法、基础知识与项目经历、联邦学习与恶意软件
+
+- [ ] 数据结构预算法——动态规划和贪心整理完成
+- [ ] 基础知识与项目经历——数据库整理完成
+- [ ] 联邦学习与恶意软件——TensorFlow学习完成part2
+
+## 收获
\ No newline at end of file
diff --git a/工作日志/2021年4月1日-今日计划.md b/工作日志/2021年4月1日-今日计划.md
new file mode 100644
index 00000000..89309266
--- /dev/null
+++ b/工作日志/2021年4月1日-今日计划.md
@@ -0,0 +1,7 @@
+## 计划
+
+> 每日计划包括三方面的内容:数据结构与算法、基础知识与项目经历、联邦学习与恶意软件
+
+- [ ] 数据结构预算法——回溯剪枝和分支限界整理完成
+- [ ] 基础知识与项目经历——计算机网络整理完成
+- [ ] 联邦学习与恶意软件——TensorFlow federated学习开始part1
diff --git a/工作日志/2021年4月2日-今日计划.md b/工作日志/2021年4月2日-今日计划.md
new file mode 100644
index 00000000..5d292eb4
--- /dev/null
+++ b/工作日志/2021年4月2日-今日计划.md
@@ -0,0 +1,7 @@
+## 计划
+
+> 每日计划包括三方面的内容:数据结构与算法、基础知识与项目经历、联邦学习与恶意软件
+
+- [ ] 数据结构预算法——图算法和随机化算法整理完成
+- [ ] 基础知识与项目经历——项目经历整理完成
+- [ ] 联邦学习与恶意软件——TensorFlow federated学习完成part2
diff --git a/操作系统/0 概述.md b/操作系统/0 概述.md
new file mode 100644
index 00000000..c5bf0273
--- /dev/null
+++ b/操作系统/0 概述.md
@@ -0,0 +1,62 @@
+# 计算机操作系统 概述
+
+> 计算机操作系统的组成
+
+
+
+## 1 操作系统引论
+
+1. 操作系统的目标和作用
+2. 操作系统的发展过程
+3. 操作系统的基本特性
+4. 操作系统的主要功能
+5. OS结构设计
+
+## 2 进程管理
+1. 进程的基本概念
+2. 进程控制
+3. 进程同步
+4. 进程通信
+5. 线程
+6. 管程
+
+## 3 处理机管理(处理机的调度与死锁)
+
+1. 处理机调度的层次
+2. 调度队列模型和调度准则
+3. 调度算法
+4. 实时调度
+5. 产生死锁
+6. 预防死锁
+7. 死锁的检测与解除
+
+## 4 存储器管理
+
+1. 存储器的层次结构
+2. 程序的装载和链接
+3. 连续分配方式
+4. 分页存储管理方式
+5. 分段存储管理方式
+6. 虚拟存储器的基本概念
+7. 请求分页存储管理的方式
+8. 页面置换算法
+9. 请求分段存储管理的方式
+
+## 5 设备管理
+
+1. IO系统
+2. IO控制方式
+3. 缓冲管理
+4. IO软件
+5. 设备分配
+6. 磁盘存储器管理
+
+## 6 文件管理
+
+1. 文件和文件系统
+2. 文件的逻辑结构
+3. 外存分配方式
+4. 目录管理
+5. 文件存储空间管理
+6. 文件共享与文件保护
+7. 数据一致性控制
\ No newline at end of file
diff --git a/操作系统/1 操作系统引论.md b/操作系统/1 操作系统引论.md
new file mode 100644
index 00000000..8d5d83f6
--- /dev/null
+++ b/操作系统/1 操作系统引论.md
@@ -0,0 +1,219 @@
+# 计算机组成
+
+> 目录
+> 1. 操作系统的目标和作用
+> 2. 操作系统的发展过程
+> 3. 操作系统的基本特性
+> 4. 操作系统的主要功能
+> 5. OS结构设计
+
+## 1 操作系统的目标和作用
+
+### 定义
+
+* 操作系统(Operating System,OS)是计算机系统最基础的系统软件,管理软硬件资源、控制程序执行,改善人机界面,合理组织计算机工作流程,为用户使用计算机提供良好运行环境。
+
+### 目标
+
+### 作用
+
+### 分类
+
+1. 操作控制方式
+ 1. 多道批处理操作系统,脱机控制方式
+ 2. 分时操作系统,交互式控制方式
+ 3. 实时操作系统
+2. 应用领域
+ 1. 服务器操作系统、并行操作系统
+ 2. 网络操作系统、分布式操作系统
+ 3. 个人机操作系统、手机操作系统
+ 4. 嵌入式操作系统、传感器操作系统
+
+### 资源分类
+
+1. 硬件资源
+ 1. 处理器资源:哪个程序占有处理器运行
+ 2. 内存资源:程序/数据在内存中如何分布
+ 3. 设备管理:如何分配、去配和使用设备
+2. 信息资源
+ 1. 数据、程序
+ 2. 信息资源管理:如何访问文件信息
+ 3. 信号量资源:如何管理进程之间的通信
+
+### 资源使用
+3. 资源使用原则:屏蔽资源使用的底层细节
+ 1. 驱动程序:最底层的、直接控制和监视各类硬件资源。职责是隐藏底层硬件的具体细节,并向其他部分提供一个抽象的、通用的接口
+4. 资源共享方式
+ 1. 独占使用方式
+ 2. 并发使用方式
+5. 资源分配策略
+ 1. 静态分配方式
+ 2. 动态分配方式
+ 3. 资源抢占方式
+
+
+
+## 2 基本特征
+
+### 2.1 并发
+
+* 并发是指宏观上在一段时间内能同时运行多个程序,而并行则指同一时刻能运行多个指令。
+
+* 并行需要硬件支持,如多流水线、多核处理器或者分布式计算系统。
+
+* 操作系统通过引入进程和线程,使得程序能够并发运行。
+
+### 2.2 共享
+
+* 共享是指系统中的资源可以被多个并发进程共同使用。
+
+* 有两种共享方式:互斥共享和同时共享。
+
+* 互斥共享的资源称为临界资源,例如打印机等,在同一时刻只允许一个进程访问,需要用同步机制来实现互斥访问。
+
+### 2.3 虚拟
+
+* 虚拟技术把一个物理实体转换为多个逻辑实体。
+
+* 主要有两种虚拟技术:时(时间)分复用技术和空(空间)分复用技术。
+
+* 多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占用处理器,每次只执行一小个时间片并快速切换。
+
+* 虚拟内存使用了空分复用技术,它将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间的页被映射到物理内存,地址空间的页并不需要全部在物理内存中,当使用到一个没有在物理内存的页时,执行页面置换算法,将该页置换到内存中。
+
+### 2.4 异步
+
+* 异步指进程不是一次性执行完毕,而是走走停停,以不可知的速度向前推进。
+
+## 3 基本功能
+
+### 进程管理
+
+* 进程控制、进程同步、进程通信、死锁处理、处理机调度等。
+
+### 内存管理
+
+* 内存分配、地址映射、内存保护与共享、虚拟内存等。
+
+### 文件管理
+
+* 文件存储空间的管理、目录管理、文件读写管理和保护等。
+
+### 设备管理
+
+* 完成用户的 I/O 请求,方便用户使用各种设备,并提高设备的利用率。
+* 主要包括缓冲管理、设备分配、设备处理、虛拟设备等。
+
+## 4 系统调用
+
+### 定义
+
+
+1. 如果一个进程在用户态需要使用内核态的功能,就进行系统调用从而陷入内核,由操作系统代为完成。
+ 1. 操作系统实现的完成某种特定功能的过程
+ 2. 为所有运行程序提供访问操作系统的接口
+2. 系统调用实现
+ 1. 编写系统调用处理程序
+ 2. 设计一张系统调用入口地址表,每个入口地址指向一个系统调用的处理程序,并包含系统调用自带参数的个数
+ 3. 陷入处理机制需开辟现场保护区,以保存发生系统调用时的处理器现场
+
+3. Linux 的系统调用主要有以下这些:
+
+| Task | Commands |
+| :---: | --- |
+| 进程控制 | fork(); exit(); wait(); |
+| 进程通信 | pipe(); shmget(); mmap(); |
+| 文件操作 | open(); read(); write(); |
+| 设备操作 | ioctl(); read(); write(); |
+| 信息维护 | getpid(); alarm(); sleep(); |
+| 安全 | chmod(); umask(); chown(); |
+
+## 5 宏内核和微内核
+
+### 宏内核
+
+* 宏内核是将操作系统功能作为一个紧密结合的整体放到内核。由于各模块共享信息,因此有很高的性能。
+
+### 微内核
+
+* 由于操作系统不断复杂,因此将一部分操作系统功能移出内核,从而降低内核的复杂性。移出的部分根据分层的原则划分成若干服务,相互独立。
+
+* 在微内核结构下,操作系统被划分成小的、定义良好的模块,只有微内核这一个模块运行在内核态,其余模块运行在用户态。
+
+* 因为需要频繁地在用户态和核心态之间进行切换,所以会有一定的性能损失。
+
+
+
+## 6 中断分类
+
+### 外中断
+
+* 由 CPU 执行指令以外的事件引起,如 I/O 完成中断,表示设备输入/输出处理已经完成,处理器能够发送下一个输入/输出请求。此外还有时钟中断、控制台中断等。
+
+### 内中断
+
+1. 异常中断。由 CPU 执行指令的内部事件引起,如非法操作码、地址越界、算术溢出等。
+2. 陷入中断。在用户程序中使用**系统调用**。
+
+
+## 7 硬件资源
+
+### 中央处理器
+
+1. 中央处理器(CPU)是计算机的运算核心(Core)和控制单元(Control Unit),主要包括:
+ 1. 运算逻辑部件:一个或多个运算器
+ 2. 寄存器部件:包括通用寄存器、控制与状态寄存器,以及高速缓冲存储器(Cache)
+ 3. 控制部件:实现各部件间联系的数据、控制及状态的内部总线;负责对指令译码、发出为完成每条指令所要执行操作的控制信号、实现数据传输等功能的部件
+2. 处理器与寄存器
+ 1. 运算单元
+ 2. 控制单元
+ 3. 内部总线
+ 4. PC/IR/Flag(程序计数器/指令暂存器/标志寄存器)
+ 5. MAR/MDR(内存地址寄存器MAR/内存数据寄存器MDR)
+ 6. 寄存器
+ 7. Cache
+ 8. IOAR/IODR
+
+### 主存储器
+
+1. 存储器的组织层次(由上到下,容量更大、速度更慢、价格更低,单位都是字节)
+ 1. L0:寄存器
+ 2. L1:L1 Cache(SRAM,静态随机存储器)
+ 3. L2:L2 Cache(SRAM)
+ 4. L3:L3 Cache(SRAM)
+ 5. L4:主存(DRAM,动态随机存储器)
+ 6. L5:SSD(本地固态硬盘)
+ 7. L6:本地外存储器(本地硬盘)
+ 8. L7:远程外存储器(分布式文件系统、Web服务器)
+
+### 外围设备
+
+1. 类型
+ 1. 输入设备
+ 2. 输出设备
+ 3. 存储设备
+ 4. 网络通信设备
+2. 控制方式
+ 1. 轮询方式:CPU忙式控制+数据交换
+ 2. 中断方式:CPU启动/中断+数据交换
+ 3. DMA方式:CPU启动/中断,DMA数据交换
+
+### 总线
+1. 定义及其组成
+ 1. 总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是CPU、内存、输入输出设备传递信息的公用通道
+ 2. 计算机的各个部件通过总线相连接,外围设备通过相应的接口电路再与总线相连接,从而形成了计算机硬件系统
+ 3. 按照所传输的信息种类,总线包括一组控制线,一组数据线和一组地址线
+2. 类型
+ 1. 内部总线:用于CPU芯片内部连接各元件
+ 2. 系统总线:用于连接CPU、存储器和各种I/O模块等主要部件
+ 3. 通信总线:用于计算机系统之间的通信
+
+## 8 软件资源
+
+1. 系统软件:操作系统、实用程序、语言处理程序、数据库管理系统
+ 1. 操作系统实施对各种软硬件资源的管理控制
+ 2. 实用程序为方便用户所设,如文本编辑等
+ 3. 语言处理程序把汇编语言/高级语言编写的程序,翻译成可执行的机器语言程序
+2. 支撑软件的有接口软件、工具软件、环境数据库
+3. 支持用户使用计算机的环境,提供开发工具也可以认为是系统软件的一部分
+4. 应用软件是用户按其需要自行编写的专用程序
diff --git a/操作系统/2 中断.md b/操作系统/2 中断.md
new file mode 100644
index 00000000..b5a032a5
--- /dev/null
+++ b/操作系统/2 中断.md
@@ -0,0 +1,130 @@
+
+# 中断
+
+## 1 定义
+
+### 广义和狭义
+
+1. 广义:程序执行过程中,遇到急需处理的事件时,暂时中止CPU上现行程序的运行,转去执行相应的事件处理程序,待处理完成后再返回原程序被中断处或调度其他程序执行的过程。
+2. 操作系统是“中断驱动”的,中断是激活操作系统的唯一方式。
+3. 狭义:处理器之外的中断事件,与当前运行指令无关的中断事件。I/O中断、时钟中断、外部信号中断。
+
+### 异常
+
+1. 当前运行指令引起的中断事件。地址异常、算术异常、处理器硬件故障。
+2. 系统异常:执行陷入指令而触发系统调用引起的中断事件。请求设备、请求I/O、创建进程。
+
+## 2 由处理器、内存储器、总线等硬件故障引起
+
+### 处理原则:
+
+1. 保护现场
+2. 停止设备
+3. 停止CPU
+4. 向操作员报告
+5. 等待人工干预
+
+### 由处理器执行机器指令引起。
+
+1. 除数为0,操作数溢出等算术异常:简单处理,报告用户;由用户编写中断续元程序处理
+2. 非法程序、用户态使用特权指令、地址越界、非法存取等指令异常:终止程序
+3. 终止进程指令:终止进程
+4. 虚拟地址异常:调整内存后重新执行指令
+
+### 处理器执行陷入指令请求OS服务引起的;在操作系统中,它一般又被称作系统调用
+
+1. 请求分配外设、请求I/O等等
+2. 处理流程:陷入OS,保护现场,根据功能号查入口地址,跳转具体处理程序
+
+### 来源于外围设备报告I/O状态的中断
+
+1. I/O完成:调整进程状态,释放等待进程
+2. I/O出错:等待人工干预
+3. I/O异常:等待人工干预
+
+### 由外围设备发出的信号引起的中断事件
+
+1. 时钟中断、间断时钟中断:记时与时间片处理
+2. 设备报到与结束中断:调整设备表
+3. 键盘/鼠标信号中断:根据信号作出相应反应
+4. 关机/重启动中断:写回文件,停止设备与CPU
+
+## 3 过程
+
+### 发现中断源,提出中断请求
+
+1. 发现中断寄存器中记录的中断
+2. 决定这些中断是否应该屏蔽
+3. 当有多个要响应的中断源时,根据规定的优先级选择一个
+
+### 中断当前程序的执行
+
+1. 保存当前程序的PSW/PC到核心栈
+
+### 转向操作系统的中断处理程序
+
+## 4 中断的处理
+
+### 中断处理程序
+
+1. 操作系统处理中断事件的控制程序,主要任务是处理中断事件和恢复正常操作
+
+### 中断处理过程
+
+1. 保护未被硬件保护的处理器状态
+2. 通过分被中断进程的PSW中断码字段,识别中断源
+3. 分别处理发生的中断事件
+4. 恢复正常操作
+ 1. 对于某些中断,在处理完毕后,直接返回刚刚被中断的进程
+ 2. 对于其他一些中断,需要中断当前进程的运行,调整进程队列,启动进程调度,选择下一个执行的进程并恢复其执行
+
+### 系统处理流程
+
+1. 运行进程
+2. 在硬件中,发现中断源,置中断码以备分析,交换新旧PSW
+3. 在操作系统中,保护未被硬件保护的现场信息,分析中断源,分别处理各类中断事件
+ 1. 调整进程队列,进程调度,恢复处理器现场信息
+ 2. 恢复处理器现场信息
+4. 在硬件中,恢复PSW
+5. 恢复进程
+
+## 5 中断屏蔽
+
+1. 当计算机检测到中断时,中断装置通过中断屏蔽位决定是否响应已发送的中断
+2. 有选择的响应中断
+
+## 6 中断优先级
+
+1. 当计算机同时检测到多个中断时,中断装置响应中断的顺序
+2. 有优先度的响应中断
+3. 一种可能的处理次序
+ 1. 处理机硬件故障中断事件、自愿性中断事件、程序性中断事件、时钟中断等外部中断事件、输入输出中断事件、重启动和关机中断事件
+4. 不同类型的操作系统有不同的中断优先级
+
+## 7 中断的嵌套处理
+
+1. 当计算机响应中断后,在中断处理过程中,可以再响应其他中断
+2. 操作系统是性能攸关程序系统,且中断响应处理有硬件要求,考虑系统效率和实现代价问题,中断的嵌套处理应限制在一定层数内,如三层
+3. 中断的嵌套处理改变中断处理次序,先响应的有可能后处理
+
+## 8 多中断的响应与处理
+
+### 决定中断处理次序的因素
+
+1. 中断屏蔽可以使中断装置不响应某些中断
+2. 中断优先级决定了中断装置响应中断的次序
+3. 中断可以嵌套处理,但嵌套的层数应有限制
+4. 中断的嵌套处理改变了中断处理的次序
+
+### 案例一
+
+1. X、Y两个中断同时发生
+2. 先响应X
+3. 因Y被屏蔽,继续处理X
+4. 再响应并处理Y
+
+### 案例二
+1. X、Y两个中断同时发生
+2. 根据中断优先级,先响应X
+3. 因未屏蔽Y,再响应并处理Y
+4. Y处理完成后,再处理X
diff --git a/操作系统/2 进程管理.md b/操作系统/2 进程管理.md
new file mode 100644
index 00000000..d78a43ff
--- /dev/null
+++ b/操作系统/2 进程管理.md
@@ -0,0 +1,836 @@
+# 进程管理
+
+## 2 进程管理
+1. 进程的基本概念
+2. 进程控制
+3. 进程同步
+4. 进程通信
+5. 线程
+6. 管程
+
+## 1 进程与线程
+
+### 进程
+
+* 进程是资源分配的基本单位。进程控制块 (Process Control Block, PCB) 描述进程的基本信息和运行状态,所谓的创建进程和撤销进程,都是指对 PCB 的操作。
+
+* 下图显示了 4 个程序创建了 4 个进程,这 4 个进程可以并发地执行。
+
+
+
+### 线程
+
+* 线程是独立调度的基本单位。一个进程中可以有多个线程,它们共享进程资源。
+
+* QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 HTTP 请求线程、事件响应线程、渲染线程等等,线程的并发执行使得在浏览器中点击一个新链接从而发起 HTTP 请求时,浏览器还可以响应用户的其它事件。
+
+
+### 区别
+
+1. 拥有资源。进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。
+2. 调度。线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
+3. 系统开销。由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。
+4. 通信方面。线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助IPC。
+
+## 2 进程状态的切换
+
+
+
+- 就绪状态(ready):等待被调度
+- 运行状态(running)
+- 阻塞状态(waiting):等待资源
+
+### 应该注意以下内容
+
+- 只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。
+- 阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态。
+
+## 3 进程调度算法
+
+* 不同环境的调度算法目标不同,因此需要针对不同环境来讨论调度算法。
+
+### 批处理系统
+
+* 批处理系统没有太多的用户操作,在该系统中,调度算法目标是保证吞吐量和周转时间(从提交到终止的时间)。
+
+1. 先来先服务 first-come first-serverd(FCFS)
+
+ * 非抢占式的调度算法,按照请求的顺序进行调度。有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。
+
+1. 短作业优先 shortest job first(SJF)
+
+ * 非抢占式的调度算法,按估计运行时间最短的顺序进行调度。长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。
+
+3. 最短剩余时间优先 shortest remaining time next(SRTN)
+
+ * 最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。
+
+### 交互式系统
+
+* 交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应。
+
+1. 时间片轮转
+
+ * 将所有就绪进程按 FCFS 的原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程。
+
+ * 时间片轮转算法的效率和时间片的大小有很大关系:
+ - 因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。
+ - 而如果时间片过长,那么实时性就不能得到保证。
+ 
+
+2. 优先级调度
+
+ * 为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。
+
+3. 多级反馈队列
+
+ * 一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法,那么需要交换 100 次。多级队列是为这种需要连续执行多个时间片的进程考虑,它设置了多个队列,每个队列时间片大小都不同,例如 1,2,4,8,..。进程在第一个队列没执行完,就会被移到下一个队列。这种方式下,之前的进程只需要交换 7 次。
+ * 每个队列优先权也不同,最上面的优先权最高。因此只有上一个队列没有进程在排队,才能调度当前队列上的进程。
+ * 可以将这种调度算法看成是时间片轮转调度算法和优先级调度算法的结合。
+ 
+
+### 实时系统
+
+ * 实时系统要求一个请求在一个确定时间内得到响应。分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。
+
+## 4 进程同步
+
+### 临界区
+
+* 对临界资源进行访问的那段代码称为临界区。为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
+
+```html
+// entry section
+// critical section;
+// exit section
+```
+
+### 同步与互斥
+
+- 同步:多个进程因为合作产生的直接制约关系,使得进程有一定的先后执行关系。
+- 互斥:多个进程在同一时刻只有一个进程能进入临界区。
+
+### 3. 信号量
+
+* 信号量(Semaphore)是一个整型变量,可以对其执行 down 和 up 操作,也就是常见的 P 和 V 操作。
+
+ - **down** : 如果信号量大于 0 ,执行 -1 操作;如果信号量等于 0,进程睡眠,等待信号量大于 0;
+ - **up** :对信号量执行 +1 操作,唤醒睡眠的进程让其完成 down 操作。
+
+down 和 up 操作需要被设计成原语,不可分割,通常的做法是在执行这些操作的时候屏蔽中断。
+
+如果信号量的取值只能为 0 或者 1,那么就成为了 **互斥量(Mutex)** ,0 表示临界区已经加锁,1 表示临界区解锁。
+
+```c
+typedef int semaphore;
+semaphore mutex = 1;
+void P1() {
+ down(&mutex);
+ // 临界区
+ up(&mutex);
+}
+
+void P2() {
+ down(&mutex);
+ // 临界区
+ up(&mutex);
+}
+```
+
+\ **使用信号量实现生产者-消费者问题** \ \
+
+问题描述:使用一个缓冲区来保存物品,只有缓冲区没有满,生产者才可以放入物品;只有缓冲区不为空,消费者才可以拿走物品。
+
+因为缓冲区属于临界资源,因此需要使用一个互斥量 mutex 来控制对缓冲区的互斥访问。
+
+为了同步生产者和消费者的行为,需要记录缓冲区中物品的数量。数量可以使用信号量来进行统计,这里需要使用两个信号量:empty 记录空缓冲区的数量,full 记录满缓冲区的数量。其中,empty 信号量是在生产者进程中使用,当 empty 不为 0 时,生产者才可以放入物品;full 信号量是在消费者进程中使用,当 full 信号量不为 0 时,消费者才可以取走物品。
+
+注意,不能先对缓冲区进行加锁,再测试信号量。也就是说,不能先执行 down(mutex) 再执行 down(empty)。如果这么做了,那么可能会出现这种情况:生产者对缓冲区加锁后,执行 down(empty) 操作,发现 empty = 0,此时生产者睡眠。消费者不能进入临界区,因为生产者对缓冲区加锁了,消费者就无法执行 up(empty) 操作,empty 永远都为 0,导致生产者永远等待下,不会释放锁,消费者因此也会永远等待下去。
+
+```c
+#define N 100
+typedef int semaphore;
+semaphore mutex = 1;
+semaphore empty = N;
+semaphore full = 0;
+
+void producer() {
+ while(TRUE) {
+ int item = produce_item();
+ down(&empty);
+ down(&mutex);
+ insert_item(item);
+ up(&mutex);
+ up(&full);
+ }
+}
+
+void consumer() {
+ while(TRUE) {
+ down(&full);
+ down(&mutex);
+ int item = remove_item();
+ consume_item(item);
+ up(&mutex);
+ up(&empty);
+ }
+}
+```
+
+### 4. 管程
+
+使用信号量机制实现的生产者消费者问题需要客户端代码做很多控制,而管程把控制的代码独立出来,不仅不容易出错,也使得客户端代码调用更容易。
+
+c 语言不支持管程,下面的示例代码使用了类 Pascal 语言来描述管程。示例代码的管程提供了 insert() 和 remove() 方法,客户端代码通过调用这两个方法来解决生产者-消费者问题。
+
+```pascal
+monitor ProducerConsumer
+ integer i;
+ condition c;
+
+ procedure insert();
+ begin
+ // ...
+ end;
+
+ procedure remove();
+ begin
+ // ...
+ end;
+end monitor;
+```
+
+管程有一个重要特性:在一个时刻只能有一个进程使用管程。进程在无法继续执行的时候不能一直占用管程,否则其它进程永远不能使用管程。
+
+管程引入了 **条件变量** 以及相关的操作:**wait()** 和 **signal()** 来实现同步操作。对条件变量执行 wait() 操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal() 操作用于唤醒被阻塞的进程。
+
+ **使用管程实现生产者-消费者问题**
+
+```pascal
+// 管程
+monitor ProducerConsumer
+ condition full, empty;
+ integer count := 0;
+ condition c;
+
+ procedure insert(item: integer);
+ begin
+ if count = N then wait(full);
+ insert_item(item);
+ count := count + 1;
+ if count = 1 then signal(empty);
+ end;
+
+ function remove: integer;
+ begin
+ if count = 0 then wait(empty);
+ remove = remove_item;
+ count := count - 1;
+ if count = N -1 then signal(full);
+ end;
+end monitor;
+
+// 生产者客户端
+procedure producer
+begin
+ while true do
+ begin
+ item = produce_item;
+ ProducerConsumer.insert(item);
+ end
+end;
+
+// 消费者客户端
+procedure consumer
+begin
+ while true do
+ begin
+ item = ProducerConsumer.remove;
+ consume_item(item);
+ end
+end;
+```
+
+## 经典同步问题
+
+生产者和消费者问题前面已经讨论过了。
+
+### 1. 哲学家进餐问题
+
+
+
+五个哲学家围着一张圆桌,每个哲学家面前放着食物。哲学家的生活有两种交替活动:吃饭以及思考。当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子。
+
+下面是一种错误的解法,如果所有哲学家同时拿起左手边的筷子,那么所有哲学家都在等待其它哲学家吃完并释放自己手中的筷子,导致死锁。
+
+```c
+#define N 5
+
+void philosopher(int i) {
+ while(TRUE) {
+ think();
+ take(i); // 拿起左边的筷子
+ take((i+1)%N); // 拿起右边的筷子
+ eat();
+ put(i);
+ put((i+1)%N);
+ }
+}
+```
+
+为了防止死锁的发生,可以设置两个条件:
+
+- 必须同时拿起左右两根筷子;
+- 只有在两个邻居都没有进餐的情况下才允许进餐。
+
+```c
+#define N 5
+#define LEFT (i + N - 1) % N // 左邻居
+#define RIGHT (i + 1) % N // 右邻居
+#define THINKING 0
+#define HUNGRY 1
+#define EATING 2
+typedef int semaphore;
+int state[N]; // 跟踪每个哲学家的状态
+semaphore mutex = 1; // 临界区的互斥,临界区是 state 数组,对其修改需要互斥
+semaphore s[N]; // 每个哲学家一个信号量
+
+void philosopher(int i) {
+ while(TRUE) {
+ think(i);
+ take_two(i);
+ eat(i);
+ put_two(i);
+ }
+}
+
+void take_two(int i) {
+ down(&mutex);
+ state[i] = HUNGRY;
+ check(i);
+ up(&mutex);
+ down(&s[i]); // 只有收到通知之后才可以开始吃,否则会一直等下去
+}
+
+void put_two(i) {
+ down(&mutex);
+ state[i] = THINKING;
+ check(LEFT); // 尝试通知左右邻居,自己吃完了,你们可以开始吃了
+ check(RIGHT);
+ up(&mutex);
+}
+
+void eat(int i) {
+ down(&mutex);
+ state[i] = EATING;
+ up(&mutex);
+}
+
+// 检查两个邻居是否都没有用餐,如果是的话,就 up(&s[i]),使得 down(&s[i]) 能够得到通知并继续执行
+void check(i) {
+ if(state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] !=EATING) {
+ state[i] = EATING;
+ up(&s[i]);
+ }
+}
+```
+
+### 2. 读者-写者问题
+
+允许多个进程同时对数据进行读操作,但是不允许读和写以及写和写操作同时发生。
+
+一个整型变量 count 记录在对数据进行读操作的进程数量,一个互斥量 count_mutex 用于对 count 加锁,一个互斥量 data_mutex 用于对读写的数据加锁。
+
+```c
+typedef int semaphore;
+semaphore count_mutex = 1;
+semaphore data_mutex = 1;
+int count = 0;
+
+void reader() {
+ while(TRUE) {
+ down(&count_mutex);
+ count++;
+ if(count == 1) down(&data_mutex); // 第一个读者需要对数据进行加锁,防止写进程访问
+ up(&count_mutex);
+ read();
+ down(&count_mutex);
+ count--;
+ if(count == 0) up(&data_mutex);
+ up(&count_mutex);
+ }
+}
+
+void writer() {
+ while(TRUE) {
+ down(&data_mutex);
+ write();
+ up(&data_mutex);
+ }
+}
+```
+
+以下内容由 [@Bandi Yugandhar](https://github.com/yugandharbandi) 提供。
+
+The first case may result Writer to starve. This case favous Writers i.e no writer, once added to the queue, shall be kept waiting longer than absolutely necessary(only when there are readers that entered the queue before the writer).
+
+```c
+int readcount, writecount; //(initial value = 0)
+semaphore rmutex, wmutex, readLock, resource; //(initial value = 1)
+
+//READER
+void reader() {
+
+ down(&readLock); // reader is trying to enter
+ down(&rmutex); // lock to increase readcount
+ readcount++;
+ if (readcount == 1)
+ down(&resource); //if you are the first reader then lock the resource
+ up(&rmutex); //release for other readers
+ up(&readLock); //Done with trying to access the resource
+
+
+//reading is performed
+
+
+ down(&rmutex); //reserve exit section - avoids race condition with readers
+ readcount--; //indicate you're leaving
+ if (readcount == 0) //checks if you are last reader leaving
+ up(&resource); //if last, you must release the locked resource
+ up(&rmutex); //release exit section for other readers
+}
+
+//WRITER
+void writer() {
+
+ down(&wmutex); //reserve entry section for writers - avoids race conditions
+ writecount++; //report yourself as a writer entering
+ if (writecount == 1) //checks if you're first writer
+ down(&readLock); //if you're first, then you must lock the readers out. Prevent them from trying to enter CS
+ up(&wmutex); //release entry section
+
+
+ down(&resource); //reserve the resource for yourself - prevents other writers from simultaneously editing the shared resource
+ //writing is performed
+ up(&resource); //release file
+
+
+ down(&wmutex); //reserve exit section
+ writecount--; //indicate you're leaving
+ if (writecount == 0) //checks if you're the last writer
+ up(&readLock); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading
+ up(&wmutex); //release exit section
+}
+```
+
+We can observe that every reader is forced to acquire ReadLock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadLock, it will be released only when there is no writer left in the queue.
+
+From the both cases we observed that either reader or writer has to starve. Below solutionadds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time.
+
+```source-c
+int readCount; // init to 0; number of readers currently accessing resource
+
+// all semaphores initialised to 1
+Semaphore resourceAccess; // controls access (read/write) to the resource
+Semaphore readCountAccess; // for syncing changes to shared variable readCount
+Semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO)
+
+void writer()
+{
+ down(&serviceQueue); // wait in line to be servicexs
+ //
+ down(&resourceAccess); // request exclusive access to resource
+ //
+ up(&serviceQueue); // let next in line be serviced
+
+ //
+ writeResource(); // writing is performed
+ //
+
+ //
+ up(&resourceAccess); // release resource access for next reader/writer
+ //
+}
+
+void reader()
+{
+ down(&serviceQueue); // wait in line to be serviced
+ down(&readCountAccess); // request exclusive access to readCount
+ //
+ if (readCount == 0) // if there are no readers already reading:
+ down(&resourceAccess); // request resource access for readers (writers blocked)
+ readCount++; // update count of active readers
+ //
+ up(&serviceQueue); // let next in line be serviced
+ up(&readCountAccess); // release access to readCount
+
+ //
+ readResource(); // reading is performed
+ //
+
+ down(&readCountAccess); // request exclusive access to readCount
+ //
+ readCount--; // update count of active readers
+ if (readCount == 0) // if there are no readers left:
+ up(&resourceAccess); // release resource access for all
+ //
+ up(&readCountAccess); // release access to readCount
+}
+
+```
+
+## 进程通信
+
+进程同步与进程通信很容易混淆,它们的区别在于:
+
+- 进程同步:控制多个进程按一定顺序执行;
+- 进程通信:进程间传输信息。
+
+进程通信是一种手段,而进程同步是一种目的。也可以说,为了能够达到进程同步的目的,需要让进程进行通信,传输一些进程同步所需要的信息。
+
+### 1. 管道
+
+管道是通过调用 pipe 函数创建的,fd[0] 用于读,fd[1] 用于写。
+
+```c
+#include
+int pipe(int fd[2]);
+```
+
+它具有以下限制:
+
+- 只支持半双工通信(单向交替传输);
+- 只能在父子进程或者兄弟进程中使用。
+
+
+
+### 2. FIFO
+
+也称为命名管道,去除了管道只能在父子进程中使用的限制。
+
+```c
+#include
+int mkfifo(const char *path, mode_t mode);
+int mkfifoat(int fd, const char *path, mode_t mode);
+```
+
+FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户进程和服务器进程之间传递数据。
+
+
+
+### 3. 消息队列
+
+相比于 FIFO,消息队列具有以下优点:
+
+- 消息队列可以独立于读写进程存在,从而避免了 FIFO 中同步管道的打开和关闭时可能产生的困难;
+- 避免了 FIFO 的同步阻塞问题,不需要进程自己提供同步方法;
+- 读进程可以根据消息类型有选择地接收消息,而不像 FIFO 那样只能默认地接收。
+
+### 4. 信号量
+
+它是一个计数器,用于为多个进程提供对共享数据对象的访问。
+
+### 5. 共享存储
+
+允许多个进程共享一个给定的存储区。因为数据不需要在进程之间复制,所以这是最快的一种 IPC。
+
+需要使用信号量用来同步对共享存储的访问。
+
+多个进程可以将同一个文件映射到它们的地址空间从而实现共享内存。另外 XSI 共享内存不是使用文件,而是使用内存的匿名段。
+
+### 6. 套接字
+
+与其它通信机制不同的是,它可用于不同机器间的进程通信。
+
+
+## 1 定义
+
+1. 操作系统必须全方位地管理计算机系统中运行的程序。因此,操作系统为正在运行程序建立一个管理实体——进程
+2. 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动
+3. 进程是操作系统进行资源分配和调度的一个独立单位
+
+### 一个进程包括五个部分
+
+1. (OS管理运行程序的)数据结构P
+2. (运行程序的)内存代码C
+3. (运行程序的)内存数据D
+4. (运行程序的)通用寄存器信息R
+5. (OS控制程序执行的)程序状态字信息PSW
+
+### 概念级的进程状态
+
+1. 运行态:进程占有处理器运行
+2. 就绪态:进程具备运行条件等待处理器运行
+3. 等待态:进程由于等待资源、输入输出、信号等而不具备运行条件
+
+### 三态模型
+
+1. 运行态→等待态:等待资源、I/O、信号
+2. 等待态→就绪态:资源满足、I/O结束、信号完成
+3. 就绪态→运行态;处理器空闲时选择更高优先权进程抢占
+4. 运行态→就绪态:运行时间片刻、有更高优先权进程
+
+### 进程挂起
+
+1. OS无法预期进程的数目与资源需求,计算机系统在运行过程中可能出现资源不足的情况
+2. 运行资源不足表现为性能低和死锁两种情况
+3. 解决办法(进程挂起):剥夺某些进程的内存及其他资源,调入OS管理的对换区,不参加进程调度,待适当时候再调入内存、恢复资源、参与运行
+4. 挂起态与等待态有着本质区别,后者占有已申请到的资源处于等待,前者没有任何资源
+
+### 进程挂起的选择与恢复
+
+1. 选择等待态、就绪态进程进入挂起等待态
+2. 运行态进程可以挂起自己
+3. 等待事件结束后,挂起就绪态
+4. 一般选择挂起就绪态进程予以恢复
+
+## 2 进程控制块(Process Control Block)
+
+### 作用
+* PCB是OS用于记录和刻画进程状态及环境信息的数据结构
+* 借助PCB,OS可以全面管理进程物理实体,刻画进程的执行现状,控制进程的执行
+### 划分
+* 标识信息
+ 1. 进程标识
+ 2. 用于存放唯一标识该进程的信息
+ 1. 系统分配的标识号
+ 2. 系统分配的进程组标识号
+ 3. 用户定义的进程名
+ 4. 用户定义的进程组名
+
+* 现场信息
+ 1. 用户可见寄存器内容
+ 2. 控制/状态寄存器内容
+ 3. 用户/核心栈指针
+ 4. 用于存放该进程运行时的处理器现场信息
+ 1. 用户可见寄存器内容:数据寄存器、地址寄存器
+ 2. 控制与状态寄存器内容:PC、IR、PSW
+ 3. 栈指针内容:核心栈与用户栈指针
+
+* 控制信息:用于存放与管理、调度进程相关的信息
+
+ 1. 调度相关信息:状态、等待事件/原因、优先级
+ 2. 进程组成信息:代码/数据地址、外存映像地址
+ 3. 队列指引元:进程队列指针、父子兄弟进程指针
+ 4. 通信相关信息:消息队列、信号量、锁
+ 5. 进程特权信息:内存访问权限、处理器特权
+ 6. 处理器使用信息:占用的处理器、时间片、处理器使用事件/已执行总时间、记账信息
+ 7. 资源清单信息:正占用的资源、已使用的资源
+
+## 3 模式切换和进程切换
+
+1. 一些中断/异常不会引起进程状态转换,不会引起进程切换,只是在处理完成后把控制权交回给被中断进程
+
+### 处理流程:
+1. (中断/异常触发)正向模式切换压入PSW/PC
+2. 保存被中断进程的现场信息
+3. 处理中断/异常
+4. 恢复被中断进程的现场信息
+5. (中断返回指令触发)逆向模式转换弹出PSW/PC
+
+## 3.1 模式切换(处理器状态切换)
+
+1. 进程切换必须在操作系统内核模式下完成,这就需要模式切换
+
+### 切换:
+
+1. 用户模式到内核模式:由中断/异常/系统调用,中断用户进程执行而触发
+2. 内核模式到用户模式:OS执行中断返回指令将控制权交还用户进程而触发
+
+### 基本工作任务
+
+1. 中断装置完成正向模式切换,包括:
+ 1. 处理器模式转为内核模式
+ 2. 保存当前进程的PC/PSW值到核心栈
+ 3. 转向中断/异常/系统调用处理程序
+2. 中断返回指令完成逆向模式转换,包括:
+ 1. 从待运行进程核心栈中弹出PSW/PC值
+ 2. 处理器模式转为用户模式
+
+## 3.2 进程切换
+### 定义
+* 进程切换指从正在运行的进程中收回处理器,让待运行进程来占有处理器运行
+* 进程切换实质上就是被中断运行进程与待运行进程的上下文切换,处理过程:
+ 1. 保存被中断进程的上下文
+ 2. 转向进程调度
+ 3. 恢复待运行进程的上下文
+
+### 工作过程
+
+1. (中断/异常等触发)正向模式切换并压入PSW
+2. 保存被中断进程的现场信息
+3. 处理具体中断/异常
+4. 把被中断进程的系统堆栈指针SP值保存到PCB
+5. 调整被中断进程的PCB信息,如进程状态
+6. 把被中断进程的PCB加入相关队列
+7. 选择下一个占用CPU运行的进程
+8. 修改被选中进程的PCB信息,如进程状态
+9. 设置被选中进程的地址空间,恢复存储管理信息
+10. 恢复被选中进程的SP值到处理器寄存器SP
+11. 恢复被选中进程的现场信息进入处理器
+12. (中断返回指令触发)逆向模式转换并弹出PSW/PC
+
+### 发生时机:进程切换一定发生在中断/异常/系统调用处理过程中
+
+1. 阻塞式系统调用、虚拟地址异常导致被中断进程进入等待态
+2. 时间片中断、I/O中断后发现更高优先级进程导致被中断进程转入就绪态
+3. 终止用系统调用、不能继续执行的异常导致被中断进程进入终止态
+
+## 4 原语与进程控制原语
+
+1. 进程控制过程中涉及对OS核心数据结构(进程表/PCB池/队列/资源表)的修改
+2. 为防止与时间有关的错误,应使用原语
+3. 原语是由于若干条指令构成的完成某种特定功能的程序,执行上具有不可分割性
+4. 原语的执行可以通过关中断实现
+5. 进程控制使用的原语称为进程控制原语
+6. 另一类常用原语是进程通信原语
+
+## 5 进程的控制与管理
+
+1. 进程创建:进程表加一项,申请PCB并初始化,生成标识,建立映像,分配资源,移入就绪队列
+2. 进程撤销:从队列中移除,归还资源,撤销标识,回收PCB,移除进程表项
+3. 进程阻塞:保存现场信息,修改PCB,移入等待队列,调度其他进程执行
+4. 进程唤醒:等待队列中移除,修改PCB,移入就绪队列(该进程优先级高于运行进程触发抢占)
+5. 进程挂起:修改状态并出入相关队列,收回内存等资源送至对换区
+6. 进程激活:分配内存,修改状态并出入相关队列
+7. 其他:如修改进程特权
+
+## 6 队列管理模块
+
+1. 队列管理模块是操作系统实现进程管理的核心模块
+2. 操作系统建立多个进程队列,包括就绪队列和等待队列
+3. 按需组织为先进先出队列与优先队列
+4. 队列中的进程可以通过PCB中的队列指引元采用单/双指引元或索引连接
+5. 出队与入队操作
+6. 进程与资源调度围绕进程队列展开
+
+## 7 关键的进程管理软件
+
+### 系统调用/中断/异常处理程序
+### 队列管理模块
+### 进程控制程序
+### 进程调度程序(独立进程居多)
+### 进程通信程序(多个程序包)
+### 终端登陆与作业控制程序、性能监控程序、审计程序等外围程序
+
+## 8 进程上下文(Process context)
+
+1. 进程的执行需要环境支持,包括CPU现场和Cache中的执行信息
+2. OS中的进程物理实体和支持进程运行的环境合成进程上下文,包括以下:
+ 1. 用户级上下文:用户程序块/用户数据区/用户栈/用户共享内存
+ 2. 寄存器上下文:PSW/栈指针/通用寄存器
+ 3. 系统级上下文:PCB/内存区表/核心栈
+3. 进程上下文刻画了进程的执行情况
+
+## 9 进程映像(Process Image)
+1. 某一时刻进程的内容及其执行状态集合
+ 1. 进程控制块:保存进程的标识信息、状态信息和控制信息
+ 2. 进程程序块:进程处理的数据空间,包括数据、处理函数的用户栈可修改的程序
+ 3. 核心栈:进程在内核模式下运行时使用的堆栈,中断或系统过程使用
+2. 进程映像是内存级的物理实体,又称为进程的内存映像
+
+## 10 线程
+### 传统进程是单线程结构进程
+#### 问题:
+
+1. 进程切换开销大
+2. 进程通信开销大
+3. 限制了进程并发的粒度
+4. 降低了并行计算的效率
+
+#### 解决思路:
+
+1. 分离两个功能,”独立分配资源“与”被调度分派执行“
+2. 进程作为系统资源分配和保护的独立单位,不需要频繁地切换
+3. 线程作为系统调度和分派的基本单位,能轻装运行,会被频繁地调度和切换
+4. 线程的出现会减少进程并发执行所付出的时空开销,使得并发粒度更细、并发性更好
+
+### 多线程环境下进程的概念
+1. 在多线程环境中,进程是操作系统中进行保护和资源分配的独立单位,具有:
+ 1. 用来容纳进程映像的虚拟地址空间
+ 2. 对进程、文件和设备的存取保护机制
+
+### 多线程环境下线程的概念
+
+1. 线程是进程的一条执行路径,是调度的基本单位,同一个进程中的所有线程共享进程获得的主存空间和资源。它具有:
+ 1. 线程执行状态
+ 2. 受保护的线程上下文,当线程不运行时,用于存储线程信息
+ 3. 独立的程序指令计数器
+ 4. 执行堆栈
+ 5. 容纳局部变量的静态存储器
+
+### 多线程环境下线程的状态与调度
+
+1. 线程状态有运行、就绪和睡眠,无挂起
+2. 与线程状态变化有关的线程操作有:
+ 1. 孵化、封锁、活化、剥夺、指派、结束
+3. OS感知线程环境下:
+ 1. 处理器调度对象是线程
+ 2. 进程没有三状态(或者说只有挂起状态)
+4. OS不感知线程环境下:
+ 1. 处理器调度对象仍是进程
+ 2. 用户空间中的用户调度程序调度线程
+
+### 并发多线程程序设计的优点
+
+1. 快速线程切换
+2. 减少(系统)管理开销
+3. (线程)通信易于实现
+4. 并行程序提高
+5. 节省内存空间
+
+### 多线程技术的应用
+
+1. 前台和后台工作
+2. C/S应用模式
+3. 加快执行速度
+4. 设计用户接口
+
+### 内核级线程(KLT,Kernel-Level Threads)
+
+1. 线程管理的所有工作由OS内核来做
+2. OS提供了一个应用程序设计接口API,供开发者使用KLT
+3. OS直接调度KLT
+4. KLT适用于解决物理并行性问题
+5. 特点
+ 1. 进程中的一个线程被阻塞了,内核能调度同一进程的其他线程占用处理器运行
+ 2. 多处理器环境中,内核能同时调度同一进程中多个线程并行执行
+ 3. 内核自身也可用多线程技术实现,能提高操作系统的执行速度和效率
+ 4. 应用程序线程在用户态运行,线程调度和管理在内核实现,在同一进程中,控制权从一个线程传送到另一个线程时需要模式切换,系统开销较大
+
+### 用户级线程(ULT,User-Level Threads)
+1. 用户空间运行的线程库,提供多线程应用程序的开发和运行支撑环境
+2. 任何应用程序均需通过线程库进行程序设计,再与线程库连接后运行
+3. 线程管理的所有工作都由应用程序完成,内核没有意识到线程的存在
+4. ULT适用于解决逻辑并行性问题
+5. 特点
+ 1. 所有线程管理数据结构均在进程的用户空间中,线程切换不需要内核模式,能节省模式切换开销和内核的宝贵资源
+ 2. 允许进程按应用特定需要选择调度算法,甚至根据应用需要裁剪调度算法
+ 3. 能运行在任何OS上,内核在支持ULT方面不需要做任何工作
+ 4. 不能利用多处理器的优点,OS调度进程,仅有一个ULT能执行
+ 5. 一个ULT的阻塞,将引起整个进程的阻塞
+
+### Jacketing技术
+
+1. 把阻塞式系统调用改造成非阻塞式的
+2. 把线程陷入系统调用时,执行jacketing程序
+3. 由jacketing程序来检查资源使用情况,以决定是否执行进程切换或传递控制权给另一个线程
+
+### 多线程实现的混合式策略
+
+1. 线程创建是完全在用户空间做的
+2. 单应用的多个ULT可以映射成一些KLT,通过调整KLT数目,可以达到较好的并行效果
+3. 特点
+ 1. 组合ULT/KLTs设施
+ 2. 线程创建完全在用户空间中完成,线程的调度和同步也在应用程序中进行
+ 3. 一个应用中的多个ULT被映射到一些(小于等于ULT数目)内核级线程上
+ 4. 程序员可以针对特定应用和机器调节KLT数目,以达到整体最佳结果
+ 5. 该方法将会结合纯粹ULT方法和KLT方法的优点,同时减少它们的缺点
+
+### 线程混合式策略下的线程状态
+
+1. KLT负责三态,系统调用负责
+2. ULT负责三态,用户调度负责
+3. 活跃态ULT代表绑定KLT的三态
+4. 活跃态ULT运行时可激活用户调度
+5. 非阻塞系统调用可使用Jacketing启动用户调度,调整活跃态ULT
diff --git a/操作系统/3 处理机管理.md b/操作系统/3 处理机管理.md
new file mode 100644
index 00000000..57fd2680
--- /dev/null
+++ b/操作系统/3 处理机管理.md
@@ -0,0 +1,84 @@
+# 处理器
+
+## 处理器调度的层次
+### 高级调度(长程调度,作业调度):决定能否加入到执行的进程池中
+
+1. 分时OS中,高级调度决定:
+ 1. 是否接受一个终端用户的连接
+ 2. 命令能否被系统接纳并构成进程
+ 3. 新建态进程是否加入就绪进程队列
+2. 批处理OS中,功能是按照某种原则从后备作业队列中选取作业进入主存,并为作业做好运行前的准备工作和完成后的善后工作
+
+### 中级调度(平衡负载调度):决定主存中的可用进程集合
+
+1. 引起中级调度是为了提高内存利用率和作业吞吐量
+2. 中级调度决定哪些进程被运行驻留在主存中参与竞争处理器及其他资源,起到短期调整系统负荷的作业
+3. 中级调度把一些进程换出内存,从而实质进入“挂起”状态,不参与进程调度,以平顺系统的负载
+
+### 低级调度(短程调度,进程调度,处理器调度):决定哪个可用进程占用处理器执行
+
+1. 按照某种原则把处理器分配给就绪态进程或KLT
+2. 进程调度程序(分派程序),操作系统中实现处理器调度的程序,是操作系统的最核心部分
+3. 处理器调度策略的优劣直接影响到整个系统的性能
+4. 功能:
+ 1. 记住进程或内核级线程的状态
+ 2. 决定某个进程或KLT什么时候获得处理器,以及占用多长时间
+ 3. 把处理器分配给进程或KLT
+ 4. 收回处理器
+
+## 2 选择处理器调度算法的原则
+
+1. 资源利用率:使得CPU或其他资源的使用率尽可能高且能够并行工作
+2. 响应时间:使交互式用户的响应时间尽可能小,或尽快处理实时任务
+3. 周转时间:提交给系统开始到执行完成获得结果为止的这段时间间隔称为周转时间,应该使周转时间或平均周转时间尽可能短
+4. 吞吐量:单位时间处理的进程数尽可能多
+5. 公平性:确保每个用户每个进程获得合理的CPU份额或其他资源份额
+
+## 3 优先数调度算法
+### 根据分配给进程的优先数决定运行进程
+
+1. 抢占式优先数调度算法
+2. 非抢占式优先数调度算法
+
+### 优先数的确定准则
+1. 进程负担任务的紧迫程度
+2. 进程的交互性
+3. 进程使用外设的频度
+4. 进程进入系统的时间长短
+
+### 与进入系统时间相关的优先数
+
+1. 计算时间短(作业/进程)优先
+2. 剩余计算时间短进程优先
+3. 响应比高者(作业/进程)优先
+ 1. 响应比=等待时间/进入时间
+4. 先来先服务:先进入先被选择
+ 1. 多用于高级调度;低级调度中,以计算为主的进程过于优越
+
+## 4 其他算法
+
+### 时间片轮转调度算法
+
+1. 根据各个进程进入就绪队列的时间先后轮流占用CPU一个时间片
+2. 时间片中断
+3. 时间片的确定:选择长短合适的时间片,过长则退化为先来先服务算法,过短则调度开销大
+4. 单时间片,多时间片和动态时间片
+
+### 分级调度算法(多队列策略,反馈循环队列)
+
+1. 建立多个不同优先级的就绪进程队列
+2. 多个就绪进程队列间按照优先数调度
+3. 高优先级就绪进程,分配的时间片短
+4. 单个就绪进程队列中进程的优先数和时间片相同
+5. 分级原则
+ 1. 一般分级原则
+ 1. 外设访问,交互性,时间紧迫程度,系统效率,用户立场,……
+ 2. 现代操作系统的实现模型
+ 1. 多个高优先级的实时进程队列,如:硬实时、网络、软实时
+ 2. 多个分时任务的进程队列,根据基准优先数和执行行为调整
+ 3. 队列数可能多达32-128个
+
+### 彩票调度算法
+
+1. 为进程发放针对系统各种资源(如CPU时间)的彩票;当调度程序需要做出决策时,随机选择一张彩票,持有该彩票的进程将获得系统资源
+2. 合作进程之间的彩票交换
diff --git a/操作系统/4 存储器管理.md b/操作系统/4 存储器管理.md
new file mode 100644
index 00000000..f84569bd
--- /dev/null
+++ b/操作系统/4 存储器管理.md
@@ -0,0 +1,390 @@
+# 存储管理
+
+## 1 逻辑地址(相对地址):用户编程所使用的地址空间
+### 逻辑地址从0开始编号,两种形式:
+1. 一维逻辑地址(地址)
+2. 二维逻辑地址(段号:段内地址)
+
+### 段式程序设计
+1. 把一个程序设计成多个段
+ 1. 代码段、数据段、堆栈段等等
+2. 用户可以自己应用段覆盖技术扩充内存空间使用量
+ 1. 这一技术是程序设计技术,不是OS存储管理的功能
+
+## 2 物理地址(绝对地址)
+1. 程序执行所使用的地址空间
+1. 处理器执行指令时按照物理地址进行
+
+## 3 主存储器的复用
+1. 多道程序设计需要复用主存
+2. 按照分区复用:
+ 1. 主存划分为多个固定/可变尺寸的分区
+ 2. 一个程序/程序段占用一个分区
+3. 按照页架复用:
+ 1. 主存划分成多个固定大小的页架
+ 2. 一个程序/程序段占用多个页架
+
+## 4 存储管理的基本模式
+1. 单连续存储管理:一维逻辑地址空间的程序占用一个主存固定分区或可变分区
+2. 段式存储管理:段式二维逻辑地址空间的程序占用多个主存可变分区
+3. 页式存储管理:一维逻辑地址空间的程序占用多个主页页架区
+4. 段页式存储管理:段式二维逻辑地址空间的程序占用多个主存页架区
+
+## 5 地址转换(重定位):把逻辑地址转换成绝对地址
+1. 静态重定位:在程序装入内存时进行地址转换
+ 1. 由装入程序执行,早期小型OS使用
+2. 动态重定位:在CPU执行程序时进行地址转换
+ 1. 从效率出发,依赖硬件地址转换机构
+
+## 6 主存储器空间的分配与去配
+1. 分配:进程装入主存时,存储管理软件进行具体的主存分配操作,并设置一个表格记录主存空间的分配情况
+2. 去配:当某个进程撤离或主动归还主存资源时,存储管理软件要收回它所占用的全部或者部分存储空间,调整主存分配表信息
+
+## 7 主存储器空间的共享
+1. 多个进程共享主存储器资源:多道程序设计技术使若干个程序同时进入主存储器,各自占用一定数量的存储空间,共同使用一个主存储器
+2. 多个进程共享主存储器的某些区域:若干个协作进程有共同的主存程序块或者主存数据块
+
+## 8 存储保护
+1. 为避免主存中的多个进程相互干扰,必须对主存中的程序和数据进行保护
+ 1. 私有主存区中的信息:可读可写
+ 2. 公共区中的共享信息:根据授权
+ 3. 非本进程信息:不可读写
+2. 这一功能需要软硬件协同完成
+ 1. CPU检查是否允许访问,不允许则产生地址保护异常,由OS进行相应处理
+
+## 9 主存储器空间的扩充
+1. 存储扩充:把磁盘作为主存扩充,只把部分进程或进程的部分内容装入内存
+ 1. 对换技术:把部分不运行的进程调出
+ 2. 虚拟技术:只调入进程的部分内容
+2. 这一工作需要软硬件协作完成
+ 1. 对换进程决定对换,硬件机构调入
+ 2. CPU处理到不在主存的地址,发出虚拟地址异常,OS将其调入,重执指令
+
+## 10 虚拟存储器思想的提出
+### 主存容量限制带来诸多不便
+1. 用户编写程序必须考虑主存容量限制
+2. 多道程序设计的道数受到限制
+
+### 用户编程行为分析
+1. 全面考虑各种情况,执行时有互斥性
+2. 顺序性和循环性等空间局部性行为
+3. 某一阶段执行的时间局部性行为
+
+### 考虑部分调入进程内容
+### 基本思想
+1. 存储管理把进程全部信息放在辅存中,执行时先将其中一部分装入主存,以后根据执行行为随用随调入
+2. 如主存中没有足够的空闲空间,存储管理需要根据执行行为把主存中暂时不用的信息调出到辅存上去
+
+### 实现思路
+1. 需要建立与自动管理两个地址空间
+ 1. (辅存)虚拟地址空间:容纳进程装入
+ 2. (主存)实际地址空间:承载进程执行
+2. 对于用户,计算机系统具有一个容量大得多的主存空间,即虚拟存储器
+3. 虚拟存储器是一种地址空间扩展技术,通常意义上对用户编程是透明的,除非用户需要进行高性能的程序设计
+
+## 11 存储管理涉及的存储对象
+ 1. 存储管理是OS管理主存储器的软件部分
+ 2. 为获得更好的处理性能,部分主存程序与数据(特别是关键性能数据)被调入Cache,存储管理需要对其进行管理,甚至包括对联想存储器的管理
+ 3. 为获得更大的虚拟地址空间,存储管理需要对存放在硬盘、固态硬盘、甚至网络硬盘上的虚拟存储器文件进行管理
+
+## 12 高速缓存存储器(Cache)
+1. Cache是介于CPU和主存储器间的高速小容量存储器,由静态存储芯片SRAM组成,容量较小但比主存DRAM技术更加昂贵而快速,接近于CPU的速度
+ 2. CPU往往需要重复读取同样的数据库,Cache的引入与缓存容量的增大,可以大幅提升CPU内部读取数据的命中率,从而提高系统性能
+3. 构成
+ 1. 高速存储器
+ 2. 联想存储器:根据内容进行寻址的存储器
+ 3. 地址转换部件:通过联想存储器建立目录表以实现快速地址转换。命中时直接访问Cache;未命中时从内存读取放入Cache
+ 4. 替换部件:在缓存已满时按一定策略进行数据块替换,并修改地址转换部件
+4. 分级:由于CPU芯片面积和成本,Cache很小。根据成本控制,划分L1,L2,L3三级
+ 1. L1 Cache:分为数据缓存和指令缓存;内置;成本最高,对CPU的性能影响最大;通常在32KB-256KB之间
+ 2. L2 Cache:分内置和外置两种,后者性能低一些;通常在512KB-8MB之间
+ 3. L3 Cache:多为外置,在游戏和服务器领域有效;但对很多应用来说,总线改善比设置L3更加有利于提升系统性能
+
+## 13 单连续分区存储管理:每个进程占用一个物理上完全连续的存储空间(区域)
+1. 主存区域划分为系统区和用户区
+2. 设置一个栅栏寄存器界分两个区域,硬件用它在执行时进行存储保护
+3. 一般采用静态重定位进行地址转换
+ 1. 静态重定位:在装入一个作业时,把该作业中程序的指令地址和数据地址全部转换成绝对地址
+4. 硬件实现代价低
+5. 适用于单用户单任务操作系统,如DOS
+
+## 14 可变分区存储管理:按照进程的内存需求来动态划分
+### 基本思想
+1. 固定分区存储管理不够灵活,既不适应大尺寸程序,又存在内存内零头,有浪费
+2. 能否按照进程实际内存需求动态划分分区,并允许分区个数可变
+
+### 创建一个进程时,根据进程所需主存量查看主存中是否有足够的空闲时间
+1. 若有,则按需要量分割一个分区
+2. 若无,则令该进程等待主存资源
+
+### 由于分区大小按照进程实际需要量来确定,因此分区个数是随机变化的
+### 内存分配
+1. 最先适应分配算法
+2. 邻近适应分配算法
+3. 最优适应分配算法
+4. 最坏适应分配算法
+
+### 内存零头
+1. 固定分区方式会产生内存内零头,可变分区方式也会随着进程的内存分配产生一些小的不可用的内存分区,称为内存外零头
+2. 最优适配算法最容易产生外零头
+3. 任何适配算法都不能避免产生外零头
+
+### 移动技术
+1. 移动分区以解决内存外零头
+2. 需要动态重定位支撑
+
+### 主存分区表
+
+#### 已分配区情况表
+
+| 起址 | 长度 | 标志 |
+| ---- | ---- | ---- |
+| 4K | 6K | J1 |
+| 46K | 6K | J2 |
+| | | 空 |
+| | | 空 |
+| ... | ... | ... |
+
+#### 未分配区情况表
+
+| 起址 | 长度 | 标志 |
+| ---- | ---- | ------ |
+| 10K | 36K | 未分配 |
+| 52K | 76K | 未分配 |
+| | | 空 |
+| | | 空 |
+| ... | ... | ... |
+
+
+## 15 固定分区存储管理
+1. 支持多个分区
+
+2. 分区数量固定
+
+3. 分区大小固定
+
+4. 可用静态重定位
+
+5. 硬件实现代价低
+
+6. 早期OS采用
+
+7. 主存分配表
+
+ | 分区号 | 起始地址 | 长度 | 占用标志 |
+ | ------ | -------- | ---- | -------- |
+ | 1 | 4K | 8K | 0 |
+ | 2 | 12K | 16K | Job1 |
+ | 3 | 28K | 16K | 0 |
+ | 4 | 44K | 24K | 0 |
+ | 5 | 68K | 24K | Job2 |
+ | 6 | 92K | 36K | 0 |
+
+
+## 16 页式存储管理
+### 基本原理
+1. 分页存储器将主存划分成多个大小相等的页架
+2. 受页架尺寸限制,程序的逻辑地址也自然分成页
+3. 不同的页可以放在不同页架中,不需要连续
+4. 页表用于维系进程的主存完整性
+
+### 地址
+1. 页式存储管理的逻辑地址由两部分组成:页号和单元号
+2. 物理地址:页架号和单元号
+3. 地址转换可以通过查页表完成
+
+### 内存分配/去配
+1. 用一张位示图来记录主存分配情况
+2. 建立进程页表维护主存逻辑完整性
+
+### 页的共享
+1. 页式存储管理能够实现多个进程共享程序和数据
+2. 数据共享:不同进程可以使用不同页号共享数据页
+3. 程序共享:不同进程必须使用相同页号共享代码页
+ 1. 共享代码页中的(JMP<页内地址>)指令,使用不同页号是做不到
+
+### 地址转换代价
+1. 页表放在主存:每次地址转换必须访问两次主存
+ 1. 按页号读出页表中的相应页架号
+ 2. 按计算出来的绝对地址进行读写
+2. 存在问题:降低了存取速度
+3. 解决办法:利用Cache存放部分页表
+
+### 快表:存放在高速存储器中的页表部分
+1. 为提供地址转换速度,设置一个专用的高速存储器,用来存放页表的一部分
+2. 快表表项:页号,页架号
+3. 这种高速存储器是联想存储器,即按照内容寻址,而非按照地址访问·
+
+### 引入快表后的地址转换代价
+1. 假设主存访问时间为200毫微秒,快表访问时间为40毫微秒,查快表的命中率是90%,平均地址转换代价为(200+40)\*90%+(200+200)\*10%=256毫微秒
+2. 比两次访问主存时间(400毫微秒)下降了36%((400-256)/400)
+
+### 基于快表的地址转换流程
+1. 按逻辑地址中的页号查快表
+2. 若该页已在快表中,则由页架号和单元号形成绝对地址
+3. 若该页不在快表中,则再查主存页表形成绝对地址,同时将该页登记到快表中
+4. 当快表填满后,又要登记新页时,则需在快表中按一定策略淘汰一个旧登记项
+
+### 多道程序环境下的进程表
+1. 进程表中登记了每个进程的页表
+
+2. 进程占有处理器运行时,其页表起始地址和长度送入页表控制寄存器
+
+3. 页表控制寄存器
+
+ | 用户作业名 | 页表地址 | 页表长度 |
+ | ---------- | -------- | -------- |
+ | AB | 0010 | 4 |
+ | CD | 0014 | 3 |
+ | EF | 0017 | 7 |
+
+### 页式虚拟存储管理
+#### 定义
+1. 把进程全部装入虚拟存储器,执行时先把部分页面装入实际内存,然后,根据执行行为,动态调入不在主存的页,同时进行必要的页面调出
+2. 现代OS的主流存储管理技术
+3. 首次只把进程第一页信息装入内存,称为请求页式存储管理
+
+页式虚拟存储管理的页表
+
+| 标志位 | 主存块号 | 辅助存储器地址 |
+| ------ | -------- | -------------- |
+| | | |
+
+扩充页表项,指出:
+
+1. 每页的虚拟地址、实际地址
+2. 主存驻留地址、写回标志、保护标志、引用标志、可移动标志
+
+#### 实现
+1. CPU处理地址
+ 1. 若页驻留,则获得块号形成绝对地址
+ 2. 若页不在内存,则CPU发出缺页中断
+2. OS处理缺页中断
+ 1. 若有空闲页架,则根据辅存地址调入页,更新页表与快表等
+ 2. 若无空闲页架,则决定淘汰页,调出已修改页,调入页,更新页表与快表
+
+### 页面调度
+1. 当主存空间已满而又需要装入新页时,页式虚拟存储管理必须按照一定的算法把已在主存的一些页调出去
+2. 选择淘汰页的工作称为页面调度
+3. 选择淘汰页的算法称为页面调度算法
+4. 页面调度算法设计不当,会出现(刚被淘汰的页面立即又要调入,并如此反复)
+5. 这种现象称为抖动或颠簸
+6. 先进先出FIFO页面调度算法
+ 1. 总是淘汰最先调入主存的那一页,或者说主存驻留时间最长的那一页(常驻的除外)
+ 2. 模拟的是程序执行的顺序性,有一定合理性
+7. 最近最少用LRU页面调度算法
+ 1. 淘汰最近一段时间较久未被访问的那一页,即那些刚被使用过的页面,可能马上还要被使用到
+ 1. OPT页面调度算法:
+ 1. 当要调入新页面时,首先淘汰以后不再访问的页,然后选择距现在最长时间后再访问的页
+ 2. 该算法由Belady提出,称为Belady算法,又称最佳算法(OPT,Optimal page replacement)
+ 3. OPT只可模拟,不可实现
+ 2. 模拟了程序执行的局部属性,既考虑了循环性又兼顾了顺序性
+ 3. 严格实现的代价大(需要维持特殊队列)
+ 4. 模拟实现:
+ 1. 每页建一个引用标志,供硬件使用
+ 2. 设置一个时间间隔中断:中断时页引用标志置0
+ 3. 地址转换时,页引用标志置1
+ 4. 淘汰页面时,从页引用标志为0z的页中间随机选择
+ 5. 时间间隔多长是个难点
+8. 最不常用LFU页面调度算法
+ 1. 淘汰最近一段时间内访问次数较少的页面,对OPT的模拟性比LRU更好
+ 2. 基于时间间隔中断,并给每一页设置一个计数器
+ 3. 时间间隔中断发生后,所有计数器清0
+ 4. 每访问页1次就给计数器加1
+ 5. 选择计数值最小的页面淘汰
+9. 时钟CLOCK页面调度算法
+ 1. 采用循环队列机制构造页面队列,形成了一个类似于钟表面的环形表
+ 2. 队列指针则相当于钟表面上的表针,指向可能要淘汰的页面
+ 3. 使用页引用标志位
+ 4. 工作流程:
+ 1. 页面调入主存时,其引用标志位置1
+ 2. 访问主存页面时,其引用标志位置1
+ 3. 淘汰页面时,从指针当前指向的页面开始扫描循环队列
+ 1. 把所遇到的引用标志位是1的页面的引用标志位清0,并跳过
+ 2. 把所遇到的引用标志位是0的页面淘汰,指针推进一步
+
+### 缺页中断率
+1. 假定进程P共n页,系统分配页架数m个
+2. P运行中成功访问次数为S,不成功访问次数为F,总访问次数A=S+F
+3. 缺页中断率定义为:f=F/A
+4. 缺页中断率是衡量存储管理性能和用户编程水平的重要依据
+5. 影响因素
+ 1. 分配给进程的页架数:可用页架数越多,则缺页中断率就越低
+ 2. 页面的大小:页面尺寸越大,则缺页中断率就越低
+ 3. 用户的程序编制方法:在大数据量情况下,对缺页中断率也有很大影响
+ ```c
+ // 程序将数组置为“0”,假定仅分得一个主存页架,页面尺寸为128个字,数组元素按行存放,开始时第一页在主存
+ int A[128][128];
+ for (int j=0;j<128;j++)
+ for (int i=0;i<128;i++)
+ A[i][j]=0;
+ // 每执行一次赋值就要产生一次缺页中断,共产生(128x128-1)次缺页中断
+
+ int A[128][128];
+ for (int i=0;i<128;i++)
+ for (int j=0;j<128;j++)
+ A[i][j]=0;
+ // 共产生(128-1)次缺页中断
+ ```
+
+### 反置页表
+#### 提出:
+1. 页面及相关硬件机制在地址转换、存储保护、虚拟地址访问中发挥了关键作用
+2. 为页式存储管理设置专门硬件机构
+3. 内存管理单元MMU:CPU管理虚拟/物理存储器的控制线路,把虚拟地址映射为物理地址,并提供存储保护,必要时确定淘汰页面
+4. 反置页表IPT:MMU用的数据结构
+
+#### 基本设计思想
+1. 针对内存中的每个页架建立一个页表,按照块号排序
+2. 表项包含:正在访问改页框的进程标识、页号及特征位和哈希链指针等
+3. 用来完成内存页架到访问进程页号的对应,即物理地址到逻辑地址的转换
+
+#### 页表项
+1. 页号:虚拟地址页号
+2. 进程标志符:使用该页的进程号(页号和进程标志符结合起来标志一个特定进程的虚拟地址空间的一页)
+3. 标志位:有效、引用、修改、保护的锁定等标志信息
+4. 链指针:哈希链
+
+#### 基于反置页表的地址转换过程
+1. MMU通过哈希表把进程标识和虚页号转换成一个哈希值,指向IPT的一个表目
+2. MMU遍历哈希链找到所需进程的虚页号,该项的索引就是页架号,通过拼接位移便可生成物理地址
+3. 若遍历整个反置页表中未能找到匹配页表项,说明该页不在内存,产生缺页中断,请求操作系统调入
+
+## 17 段式存储管理
+### 段式程序设计
+1. 每个程序可由若干段组成,每一段都可以从“0”开始编址,段内的地址是连续的
+2. 分段存储器的逻辑地址由两部分组成,段号、单元号
+
+### 基本思想
+1. 段式存储管理基于可变分区存储管理实现,一个进程要占用多个分区
+2. 硬件需要增加一组用户可见的段地址寄存器(代码段、数据段、堆栈段、附加段),供地址转换使用
+3. 存储管理需要增加设置一个段表,每个段占用一个段表项,包括:段始址、段限长,以及存储保护、可移动、可扩充等标志位
+
+### 段的共享
+1. 通过不同进程段表中的项指向同一个段基址来实现
+2. 对共享段的信息必须进行保护,如规定只能独处不能写入,不满足保护条件则产生保护中断
+
+### 段式虚拟存储管理的基本思想
+1. 把进程的所有分段都存放在辅存中,进程运行时先把当前需要的一段或几段装入主存,在执行过程中访问到不在主存的段时再把它们动态装入
+2. 段式虚拟存储管理中段的调进调出是由OS自动实现的,对用户透明
+3. 与段覆盖技术不同,它是用户控制的主存扩充技术,OS不感知
+
+### 段表扩充
+1. 特征位:00(不在内存)01(在内存)11(共享段)
+
+2. 存取权限:00(可执行)01(可读)11(可写)
+
+3. 扩充位:0(固定长)1(可扩充)
+
+4. 标志位:00(未修改)01(已修改)11(不可移动)
+
+ | 段号 | 特征 | 存取权限 | 扩充位 | 标志位 | 主存始址 |
+ | ---- | ---- | -------- | ------ | ------ | -------- |
+ | | | | | | |
+
+### 段页式存储管理
+1. 基本思想
+ 1. 段式存储管理可以基于页式存储管理实现
+ 2. 每一段不必占据连续的存储空间,可存放在不连续的主存页架中
+ 3. 能够扩充为段页式虚拟存储管理
+ 4. 装入部分段,或者装入段中部分页面
diff --git a/操作系统/5 设备管理.md b/操作系统/5 设备管理.md
new file mode 100644
index 00000000..bf1da680
--- /dev/null
+++ b/操作系统/5 设备管理.md
@@ -0,0 +1,345 @@
+# I/O存储管理
+
+## 1 I/O设备(外围设备,外部设备,外设)
+### 定义
+1. 现代计算机系统通常配备大量的I/O设备,用于计算机系统与外部世界(如用户、其他计算机或电子设备等)进行信息交换或存储
+2. I/O操作:内存和I/O设备之间的信息传送操作
+ 1. 不仅影响计算机的通用性和可扩充性,也是计算机系统综合处理能力及性价比的重要因素
+
+### 分类
+1. 按信息传输方向划分
+ 1. 输入设备:将外界信息输入计算机(键盘、鼠标、扫描仪等)
+ 2. 输出设备:将计算结果输出(显示器、打印机等)
+ 3. 输入输出设备:既可以输入信息,也可以输出信息(磁盘驱动器、网卡等)
+2. 按交互功能划分
+ 1. 人机交互设别:用于用户与计算机之间的交互通信(鼠标、键盘、显示器等)
+ 2. 存储设备:持久性存储大量信息并快速检索(磁盘驱动器、光盘驱动器等)
+ 3. 机机通信设备:用于计算机和计算机之间的通信(网卡、调制解调器等)
+3. 按设备管理划分
+ 1. 字符设备:以字符为单位进行信息交换,发送或接收一个字符流(鼠标、显示器等)
+ 2. 块设备:以固定大小的数据块(块是存储介质上联系信息组成的一个区域)进行信息交换(磁盘驱动器等)
+ 3. 网络设备:用于与远程设备通信的设备(网卡等,可以抽象为传送字符流的特殊字符设备,也可以抽象为传送连续小块数据的块设备)
+
+### 设备管理目标
+1. 克服设备和CPU速度的不匹配所引起的问题,使主机和设备并行工作,提高设备使用效率
+2. 对设备进行抽象,屏蔽设备的物理细节和操作过程,配置驱动程序,提供统一界面,供用户或高层软件使用
+ 1. 抽象为文件系统中的节点,统一管理
+ 2. 裸设备:不被操作系统直接管理,由应用程序读写,I/O效率更高
+
+### 设备管理功能
+1. 设备中断处理
+2. 缓冲区处理
+3. 设备的分配和去配
+4. 设备驱动调度
+5. 实现虚拟设备
+
+### 设备管理层次
+1. I/O硬件
+ 1. I/O设备及其接口线路
+ 2. 控制部件
+ 3. 通道
+2. I/O软件
+ 1. 系统I/O软件
+ 2. 用户空间I/O软件
+
+## 2 设备控制器(设备适配器、I/O控制器、I/O控制接口、I/O模块或I/O接口)
+### 定义
+1. 为达到模块化和通用性的设计目标,通常将I/O设备中的机械部件和电子部件分开处理
+2. 其中,电子部件称为设备控制器
+3. 操作系统与控制器交互,而非与设备交互
+
+### 功能:CPU与设备之间的接口
+1. 接收和识别CPU或通道发来的命令
+2. 实现数据交换
+3. 发现和记录设备及自身的状态信息,供CPU处理使用
+4. 当连接多台设备时,设备地址识别
+
+### 组成部分
+1. 状态/控制寄存器
+2. 数据缓冲寄存器
+3. 地址译码器和I/O控制逻辑
+4. 外设接口控制逻辑
+5. P.S
+ 1. 主机侧(I/O总线)接1、2、3
+ 2. 设备侧(接口电缆)接4(多个)
+ 3. 数据线连接1和2,地址线和控制线接3,数据状态控制接4
+ 4. 1,2与3连接,4与3连接
+
+### 轮询方式
+1. 流程:
+ 1. 处理器向控制器发送一个I/O命令
+ 2. 如果设备未就绪,则重复测试过程,直至设备就绪
+ 3. 执行数据交换
+ 4. 等待I/O操作完成后,才可以继续其他操作
+2. 处理I/O请求会终止原程序的执行
+3. CPU需要等待I/O设备就绪
+4. CPU需要参与数据传送
+5. CPU和设备只能串行工作,效率低下
+
+### 中断方式
+1. 流程:
+ 1. 处理器向控制器发出一个I/O命令,然后继续执行后续指令
+ 1. 如果该进程不需要等待I/O完成,后续指令可以仍是该进程中的指令
+ 2. 否则,该进程在这个中断上挂起,处理器执行其他工作
+ 2. 控制器检查设备状态,就绪后发起中断
+ 3. CPU响应中断,转向中断处理程序
+ 4. 中断处理程序执行数据读写操作
+ 5. 恢复执行原先的程序
+2. 响应中断后会终止原程序的执行
+3. CPU不需要等待I/O设备就绪
+4. CPU需要参与数据传送
+5. CPU和设备部分并行操作,效率有所提高
+
+### 直接存储器访问(DMA)
+1. DMA模块:模仿处理器来控制主存和设备控制器之间的数据交换
+2. 流程:
+ 1. 处理器向DMA模块发出I/O命令
+ 2. 处理器继续执行其他工作,DMA模块负责传送全部数据
+ 3. 数据传送结束后,DMA中断处理器
+3. 方式
+ 1. CPU不会终止原程序的执行
+ 2. CPU只在数据传送的开始和结束时参与
+ 1. 开始时,CPU需要对DMA模块进行初始化
+ 2. 结束时,CPU响应中断,但不必保存现场
+ 3. 周期窃取
+ 1. 当DMA和CPU同时经总线访问内存时,CPU总是将总线的占有权让给DMA一个或几个主存周期
+ 2. 周期窃取对延迟CPU与主存的数据交换影响不大
+ 1. 数据传送过程是不连续的和不规则的
+ 2. CPU大部分情况下与Cache进行数据交换,直接访问内存较少
+
+### I/O通道(通道控制器、I/O处理器)
+1. 设备控制器包含自身专用的处理器和通道程序
+ 1. I/O指令不再由处理器执行,而是存在主存中,由I/O通道所包含的处理器执行
+ 2. 采用四级连接:处理器,通道,控制器,设备
+ 1. 可控制多台同类或不同类的设备
+ 3. 流程:
+ 1. CPU在遇到I/O请求,启动指定通道
+ 2. 一旦启动成功,通道开始控制I/O设备进行操作,CPU执行其他任务
+ 3. I/O操作完成后,I/O通道发出中断,CPU停止当前工作,转向处理I/O操作结束事件
+ 4. CPU与通道并行工作
+ 5. 带有局部存储器的I/O通道
+ 1. 相当于一台自治的计算机:I/O指令存储在控制器自带的局部存储器中,并由I/O通道所包含的处理器执行
+ 6. 可以控制大量的I/O设备,同时最小化CPU的干涉
+ 7. 常用于交互式终端通信,负责包括控制终端在内的大部分任务
+
+### I/O控制方式的演化
+1. 采用轮询方式的设备控制器:CPU需要等待设备就绪,且参与数据传送
+2. 采用中断方式的设备控制器:CPU无需等待设备就绪,但响应中断后参与数据传送
+3. 通过DMA直接控制存储器:CPU在数据传送开始和结束时参与,与主存进行数据交换时不参与
+
+### I/O发展对总线的影响
+#### 单总线
+1. 将CPU、主存和I/O模块连接到同一组总线上
+2. 优点:结构简单,易于扩充
+3. 缺点:主存需要和I/O模块共用总线;设备增多会造成总线变长,进而增加传输时延;无法适用于大量高速设备
+
+#### 传统的三级总线
+1. 主存和Cache通过主存总线传送数据,主存总线和扩展总线上的I/O设备之间传送数据通过扩展总线接口缓冲
+2. 优点:主存与I/O之间的数据传送与处理器的活动分离;可以支持更多的I/O设备
+3. 缺点:不适用于I/O设备数据速率相差太大的情形
+
+#### 采用南北桥的多级总线
+1. 通过存储总线、PCI总线、E(ISA)总线分别连接主存、高速I/O设备和低速I/O设备
+2. 优点:可以支持不同数据速率的I/O设备
+
+#### 采用I/O通道的多级总线
+1. 支持CPU、主存和多个I/O通道之间的数据传送
+2. 支持I/O通道和I/O控制器,以及I/O控制器,以及I/O控制器和设备之间的数据传送
+
+## 3 I/O软件
+### 设计目标
+1. 高效率:改善设备效率,尤其是磁盘I/O操作的效率
+2. 通用性:用统一的标准来管理所有设备
+
+### 设计思路
+1. 把软件组织称层次结构,低层软件用来屏蔽硬件细节,高层软件向用户提供简洁、友善的界面
+
+### 主要考虑的问题
+1. 设备无关性:编写访问文件的程序与具体设备无关
+2. 出错处理:低层软件能处理的错误不让高层软件感知
+3. 同步/异步传输:支持阻塞和中断驱动两种工作方式
+4. 缓冲技术:建立数据缓冲区,提高吞吐率
+
+## 4 I/O中断处理程序
+1. 位于操作系统底层,与硬件设备密切相关,与系统其余部分尽可能少地发生联系
+2. 进程请求I/O操作时,通常被挂起,直到数据传输结束后并产生I/O中断时,操作系统接管CPU后转向中断处理程序
+3. 当设备向CPU提出中断请求时,CPU响应请求并转入中断处理程序
+4. 功能:
+ 1. 检查设备状态寄存器内容,判断产生中断的原因,根据I/O操作的完成情况进行相应的处理
+ 1. 如果数据传输有错,向上层软件报告设备的出错信息,实施重新执行
+ 2. 如果正常结束,唤醒等待传输的过程,使其转换为就绪态
+ 3. 如果有等待传输的I/O命令,通知相关软件启动下一个I/O请求
+
+## 5 设备驱动程序
+1. 包括与设备密切相关的所有代码
+2. 从独立于设备的软件中接收并执行I/O请求
+ 1. 把用户提交的逻辑I/O请求转化为物理I/O操作的启动和执行
+ 2. 监督设备是否正确执行,管理数据缓冲区,进行必要的纠错处理
+3. 功能:
+ 1. 设备初始化
+ 1. 在系统初次启动或设备传输数据时,预置设备和控制器以及通道状态
+ 2. 执行设备驱动例程
+ 1. 负责启动设备,进行数据传输
+ 2. 对于具有通道方式,还负责生成通道指令和通道程序,启动通道工作
+ 3. 调用和执行中断处理程序
+ 1. 负责处理设备和控制器及通道所发出的各种中断
+4. 层次:
+ 1. 每个设备驱动程序只处理一种设备,或者一类紧密相关的设备
+ 2. 设备驱动程序分为整体驱动程序和分层驱动程序
+ 1. 整体驱动程序直接向操作系统提供接口和控制硬件
+ 1. 适用于功能简单的驱动程序,效率较高,但较难迁移
+ 2. 分层驱动程序将驱动程序分成多层,放在栈中,系统接到I/O请求时先调用栈顶的驱动程序,栈顶的驱动程序可以直接处理请求或向下调用更底层的驱动程序,直至请求被处理
+ 1. 适用于功能复杂,重用性要求较高的驱动程序,结构清晰且便于移植,但会增加一部分系统开销
+
+## 6 独立于设备的I/O软件
+1. 执行适用于所有设备的常用I/O功能,并向用户层软件提供一致性接口
+2. 功能:
+ 1. 设备命名:通过路径名寻址设备
+ 2. 设备保护:检查用户是否有权访问所申请设备
+ 3. 提供与设备无关的数据单位:字符数量,块尺寸
+ 4. 缓冲技术:传输速率,时间约束,不能直接送达目的地
+ 5. 设备分配和状态跟踪:分配到不同类型的设备
+ 6. 错误处理和报告:驱动程序无法处理的错误
+
+## 7 用户空间的I/O软件
+### 库函数
+ 1. 一小部分I/O软件不在操作系统中,是与应用程序链接在一起的库函数,甚至完全由运行于用户态的程序组成
+ 2. 系统调用通常由库函数封装后供用户使用,封装函数只是将系统调用所用的参数放在合适位置,然后执行访管指令来陷入内核,再由内核函数实现真正的IO操作
+### SPOOLing软件
+ 1. 在内核外运行的系统I/O软件,采用预输入、缓输出和井管理技术,通过创建守护进程和特殊目录解决独占型设备的空占问题
+## 8 I/O缓冲
+### 目的:解决CPU与设备之间速度不匹配的矛盾,协调逻辑记录大小和物理记录大小不一致的问题,提高CPU和设备的并行性,减少I/O操作对CPU的中断次数,放宽对CPU中断响应时间的要求
+### 缓冲区:在内存中开辟的存储区,专门用于临时存放I/O操作的数据
+### 操作:
+1. 写操作:将数据送至缓冲区,直到装满,进程继续计算,同时系统将缓冲区的内容写到设备上
+2. 读操作:系统将设备上的物理记录读至缓冲区,根据要求将当前所需要的数据从缓冲区中读出并传送给进程
+
+### 单缓冲:操作系统在主存的系统区中开设一个缓冲区
+1. 输入:将数据读至缓冲区,系统将缓冲区数据送至用户区,应用程序对数据进行处理,同时系统读入接下来的数据
+2. 输出:把数据从用户区复制到缓冲区,系统将数据输出后,应用程序继续请求输出
+
+### 双缓冲:使用两个缓冲区
+1. 输入:设备先将数据输入缓冲区1,系统从缓冲区1把数据传到用户区,供应用程序处理,同时设备将数据传送到缓冲区2
+2. 输出:应用程序将数据从用户传送到缓冲区1,系统将数据传送到设备,同时应用程序将数据传送到缓冲区2
+
+### 循环缓冲:操作系统分配一组缓冲区,每个缓冲区都有指向下一个缓冲区的链接指针,构成循环缓冲
+1. 解决设备和进程速度不匹配的问题
+2. 为系统公共资源,供进程共享并由系统统一分配和管理
+
+## 9 设备独立性
+1. 作业执行前会对设备提出申请时,指定某台具体的物理设备会让设备分配变得简单,但如果所指定设备出现故障,即便计算机系统中有同类设备也不能运行
+2. 设备独立性
+1. 用户通常不指定物理设备,而是指定逻辑设备,使得用户作业和物理设备分离开来,再通过其他途径建立逻辑设备和物理设备之间的映射
+3. 设备管理中需要将逻辑设备名转换为物理设备名,为此系统需要提供逻辑设备名和物理设备名的对应表以供转换使用
+4. 微型计算机的操作系统中不一定支持设备独立性
+5. 优点:
+ 1. 应用程序与具体物理设备无关,系统增减或变更设备时不需要修改源程序
+ 2. 易于应对I/O设备故障,提高系统可靠性
+ 3. 增加设备分配的灵活性,更有效地利用设备资源,实现多道程序设计
+
+## 10 设备分配方式
+### 独占设备
+1. 只能由一个进程独占式使用
+2. 可以让多个进程同时使用的设备称为"共享设备“,其管理工作主要是驱动调度和实施驱动,一般不必分配
+
+### 分配方式
+1. 静态分配:实现简单,能够防止系统发生死锁,但会降低设备利用率
+2. 动态分配:提高设备利用率
+
+## 11 设备分配的数据结构
+### 设备类表
+1. 每类设备对应于设备类表的中一栏
+2. 包括:设备类,总台数,空闲台数,设备表起始地址等
+3. 支持设备独立性时才会使用
+
+### 设备表
+1. 每类设备都有各自的设备表,用来登记这类设备中的每台物理设备
+2. 包括:物理设备名(号),逻辑设备名(号),占有设备的进程号,是否分配,好/坏标志等
+
+## 12 磁盘结构
+### 基本概念
+1. 磁盘由多个盘片组成
+2. 每个盘片被划分为多个同心圆结构的磁道
+ 1. 不同盘片上位于相同位置的磁道构成的圆柱体称为柱面
+3. 每个磁道分为固定多个或不等个数的扇区
+ 1. 为了对大量扇区寻址,操作系统将相邻的扇区组合成簇存储文件
+4. 物理块(扇区)地址:(柱面号,磁头号,扇区号)
+ 1. 区别:“0面0道”中的“面”是指磁头,不是柱面
+
+### 磁盘读写数据
+1. 读写数据时,磁头必须定位到指定的磁道上的指定扇区的开始处
+2. 过程:
+ 1. 寻道:控制移动臂到达指定柱面,选择磁头号
+ 2. 旋转:等待要读写的扇区旋转到磁头下
+ 3. 数据传送
+
+### 磁盘存取时间:磁盘完成数据读写所需要的时间
+1. 寻道时间、旋转延迟、传送时间的总和 $T_a=T_s+\frac{1}{2r}+\frac{b}{rN}$
+2. Ta:存取时间
+3. Ts:寻道时间
+4. r:磁盘旋转速度(单位:转/秒)
+5. B:要传送的字节数
+6. N:一个磁道中的字节数
+
+### 磁盘调度策略
+1. 磁盘可能同时接收到若干I/O请求
+ 1. 如果随机选择并响应I/O请求,可能得到最坏的性能
+2. 驱动调度
+ 1. 系统采用一种调度策略,能够按最佳次序执行要求访问磁盘的多个I/O请求
+ 2. 能减少为若干I/O请求服务所需要消耗的总时间
+3. 策略
+ 1. 移臂调度
+ 1. 目的:使移动臂的移动时间最短,从而减少寻道总时间
+ 2. 调度策略
+ 1. 先进先出
+ 1. 移动臂是随机移动,寻道性能较差
+ 2. 按顺序处理请求,对所有进程公平
+ 2. 最短查找时间优先
+ 1. 先执行查找时间最短的请求,具有较好的寻道性能
+ 2. 存在"饥饿”现象
+ 3. 扫描算法
+ 1. 单向扫描
+ 1. 移动臂总向一个方向扫面,归途中不提供服务
+ 2. 适用于不断有大量柱面均匀分布的请求的情形
+ 2. 双向扫描
+ 1. 移动臂每次向一个方向移动,遇到最近的I/O请求便进行处理,到达最后一个柱面后再向相反方向移动
+ 2. 对最近扫描所跨越区域的请求响应较慢
+ 3. 电梯调度
+ 1. 无请求时移动臂停止不动,有请求时按电梯规律移动
+ 2. 每次选择沿移动臂的移动方向最近的柱面
+ 3. 如果当前移动方向上没有但相反方向有请求时,改变移动方向
+ 2. 旋转调度
+ 1. 目的:使得选择延迟的总时间最少
+ 2. 循环排序
+ 1. 通过优化I/O请求排序,在最少旋转圈数内完成位于同一柱面的访问请求
+ 2. 旋转位置测定硬件和多磁头同时读写技术有利于提高旋转调度的效率
+ 3. 优化分布
+ 1. 通过信息在存储空间的排列方式来减少旋转延迟
+ 2. 交叉因子
+ 1. 如果沿着磁道按序对扇区编号,可能由于磁盘转速太快,造成处理当前扇区的数据时,下一个扇区已经跳过,需要再转一圈才能继续读数据。因此,对扇区编号时会间隔编号,例如交叉因子为2:1表示相邻编号之间会间隔1个扇区,3:1表示会间隔2两个扇区
+ 3. 按柱面而非盘面进行数据读写
+ 1. 连续记录数据时,先记录在同一柱面的不同磁道上,然后再更换柱面,可以减少数据读写时的移臂操作
+
+## 13 虚拟设备
+### 使用一类物理设备模拟另一类物理设备的技术。比如:内存卡模拟磁盘、块设备模拟字符设备、输入输出重定向……
+### 经典的SPOOLing系统
+1. 为存放输入数据和输出数据,系统在磁盘上开辟输入井和输出井
+ 1. 井是用作缓冲的存储区域
+2. 组成
+ 1. 预输入程序:将数据从输入设备传送到磁盘输入井
+ 2. 缓输出程序:将数据从磁盘输出井传送到输出设备
+ 3. 井管理程序:控制作业和井之间的数据交换
+3. 作用
+ 1. 预输入:操作系统将作业需要的输入数据成批从输入设备上预先输入至磁盘的输入缓冲区中暂存
+ 1. 调度作业执行时,作业使用数据不必再启动输入设备,从磁盘的输入缓冲区读入即可
+ 2. 缓输出:作业不启动输出设备,只是将输出数据暂存到磁盘的输出缓冲区
+ 1. 作业执行完毕后,由操作系统成批输出
+4. 不仅设备利用率提高,作业的运行时间也会缩短,每个作业都感觉各自拥有所需的独占设备
+
+### 打印机SPOOLing
+1. 打印机空占问题
+ 1. 如果用户进程通过打开打印机的设备文件来申请和使用打印机,往往会造成该进程打开设备文件后长达数小时不用,但其他进程又无法使用打印机
+2. 打印机守护进程和SPOOLing打印目录
+ 1. 守护进程是唯一有特权使用打印机设备的进程
+ 2. 打印文件前,用户进程先产生完整的带输出文件,并存放在打印目录下
+ 3. 打印机空闲时,启动守护进程,打印带输出文件
diff --git a/操作系统/6 文件系统.md b/操作系统/6 文件系统.md
new file mode 100644
index 00000000..108b1b33
--- /dev/null
+++ b/操作系统/6 文件系统.md
@@ -0,0 +1,347 @@
+# 文件系统
+
+## 1 文件
+### 定义
+* 具有符号名的,在逻辑上具有完整意义的一组相关信息项的序列
+* 文件(document)与计算机文件(file)
+* 文件名是由字母、数字和其他符合组成的一个字符串,其格式和长度因系统而异
+### 命名:
+1. 文件名和拓展名:前者用于识别文件,后者用于标识文件特性,二者用'.'隔开
+2. 不同OS有约定的拓展名,Unix不做介绍,Windows如下
+ 1. COM:可执行的浮动二进制代码文件
+ 2. EXE:可执行的浮动二进制代码文件
+ 3. LIB:库程序文件
+ 4. BAT:批命令文件
+ 5. OBJ:编译或汇编生成的目标文件
+
+### 分类:
+1. 按用途:系统文件、库文件、用户文件
+2. 按保护级别:只读文件、读写文件、不保护文件
+3. 按信息时限:临时文件、永久文件、档案文件
+4. 按设备类型:磁盘文件、磁带文件、光盘文件、软盘文件
+5. 按逻辑结构或物理结构
+
+### 优点:
+1. 用户使用方便,按名存取
+2. 文件安全可靠,提供保护措施
+3. 文件可备份,可组织重执
+4. 文件可共享:提供利用率
+5. 把数据组织成文件形式加以管理和控制是计算机数据管理的重大进展
+
+## 2 文件系统
+1. 操作系统中负责存取和管理信息的模块,它用统一的方式管理用户和系统信息的存储、检索、更新、共享和保护,并为用户提供一整套方便有效的文件使用和操作方法
+2. 反映了用户概念中的逻辑结构,而且和存放它的辅助存储器(文件存储器)的存储结构紧密相关。同一个文件必须从逻辑文件和物理文件两个侧面来观察它
+
+### 功能(面向用户):
+1. 文件的按名存取
+2. 文件的共享和保护
+3. 文件的操作和使用
+
+### 实现功能:
+1. 文件目录的建立和维护
+2. 存储空间的分配和回收
+3. 数据的保密和保护
+4. 监督用户存取和修改文件的权限
+5. 实现在不同存储介质上信息的标识方式、编址方法、存储次序,以及信息检索等问题
+
+### 组成:
+#### 文件组织
+1. 组织方法
+ 1. 逻辑结构
+ 1. 流式文件
+ 2. 记录式文件
+ 2. 物理结构
+ 1. 顺序文件
+ 2. 连接文件
+ 3. 直接文件
+ 4. 索引文件
+
+#### 文件存取
+1. 存取方法
+ 1. 概念
+ 1. 操作系统为用户程序提供的使用文件的技术和手段
+ 2. 在某种程度上依赖于文件的物理结构
+ 2. 方法
+ 1. 顺序存取
+ 1. 按记录顺序进行读/写操作的存取方法
+ 2. 读操作根据读指针读出当前 记录,同时推进读指针,指向下一次要读出的记录
+ 3. 写操作则设置写指针,把一个记录写道文件末端,同时推进写指针
+ 4. 允许对读指针进行前跳或后退n(整数)个记录的操作
+ 2. 直接存取
+ 1. 很多应用场合要求快速地以任意次序直接读写某个记录。航空订票系统,把特定航班的所有信息存放在物理块中,用户预定某航班时,直接计算出该航班的存位置
+ 3. 索引存取
+ 1. 基于索引文件的索引存取方法
+ 2. 对于这种文件,信息块的地址都可以通过查找记录键而换算出
+ 3. 除可采用按键存取外,也可以采用顺序存取或直接存取的方法
+ 4. 实际的系统中,大都采用多级索引,以加速记录查找过程
+
+#### 文件控制
+1. 控制系统
+ 1. 逻辑的控制系统
+ 2. 物理的控制系统
+
+#### 文件使用
+1. 文件操作
+ 1. 打开文件
+ 2. 关闭文件
+ 3. 读
+ 4. 写
+ 5. 控制
+
+## 3 卷和块
+1. 文件存储介质有磁盘、光盘和磁盘
+2. 卷:存储介质的物理单位,对应于一盘磁带、一块软盘、一个光盘片、一个硬盘分区
+3. 块:存储介质上连续信息所组成的一个区域,也叫做物理记录
+4. 块在主存储器和辅助存储器进行信息交换的物理单位,每次总是交换一块或整数块信息
+5. 决定块的大小要考虑用户使用方式、数据传输效率和存储设备类型等多种因素
+6. 不同类型的存储介质,块的长短常常各不相同;对同一类型的存储介质,块的大小一般相同,但也可以不同
+7. 外围设备由于启停机械动作或识别不同块的要求,两个相邻块之间必须留有间隙
+ 1. 间隙是块之间不记录用户代码信息的区域
+8. 顺序存取存储设备的信息安排
+ 1. 顺序存取设备是严格依赖信息的物理位置次序进行定位和读写的存储设备
+ 2. 磁带机是最常用的一种顺序存取存储设备,它具有存储容量大、稳定可靠、卷可装卸和便于保存等优点,广泛用作存档
+ 3. 磁带的一个突出特点是块长的变化范围较大,块可以很小,也可以很大,原则上没有限制
+ 4. 光盘也是一种顺序存取存储设备
+9. 直接存取存储设备的信息安排
+ 1. 磁盘是一种直接存取存储设备(随机存取存储设备)
+ 2. 移臂与旋转两维组织,存取速度高
+ 3. 它的每个物理记录有确定的位置和唯一的地址,存取任何一个物理块所需的时间几乎不依赖于此信息的位置
+
+## 4 逻辑文件(文件的逻辑结构)
+### 定义
+* 独立于物理环境的,用户概念种的抽象信息组织方式
+* 用户能观察到的,并加以处理的数据集合
+
+### 文件的逻辑结构分为两种形式
+* 流式文件
+ 1. 文件内的数据不再组成记录,只是由一串依此的字节组成的信息流序列
+ 2. 这种文件常常按长度来读取所需信息,也可以用插入的特殊字符作为分界
+
+* 记录式文件
+ 1. 一种有结构的文件,它是若干逻辑记录信息所组成的记录流文件
+ 2. 逻辑记录是文件种按信息在逻辑上的独立含义所划分的信息单位
+
+* 记录式文件与数据库
+ 1. 数据库管理系统也支持逻辑记录
+ 2. 区别:数据库种的记录之间可以通过数据冗余构成某种联系
+ 3. 数据库管理系统支持基于联系的数据查询,文件系统则不行
+
+## 5 物理文件(文件的物理结构)
+1. 文件的物理结构和组织是指文件在物理存储空间种的存放方法和组织关系
+2. 文件的存储结构涉及块的划分、记录的排列、索引的组织、信息的搜索等许多问题
+3. 其优劣直接影响文件系统的性能
+4. 顺序文件(连续文件)
+ 1. 将一个文件中逻辑上连续的信息存放到存储介质的依此相邻的块中便形成顺序结构
+ 2. 磁带文件、光盘文件是典型例子
+ 3. 优点(顺序存取记录时速度较快):
+ 1. 批处理文件,系统文件用得最多
+ 2. 采用磁盘存放顺序文件时,总可以保持快速存取的优点
+ 4. 缺点:
+ 1. 建立文件前需要能预先确定文件长度,以便分配存储孔空间
+ 2. 修改、插入和增加文件记录有困难
+5. 连接文件(串联文件)
+ 1. 特点:使用连接字来表示文件中各个物理块之间的先后次序
+ 2. 每一块文件信息的物理地址由文件目录给出,而每一块的连接字指出了文件的下一个物理块位置;连接字内容为0时,表示文件至本块结束
+ 3. 像输入井、输出井等都用此类文件
+ 4. 优点:
+ 1. 易于对文件记录做增删改,易于动态增长记录
+ 2. 不必预先确知文件长度
+ 3. 存储空间利用率高
+ 5. 缺点:
+ 1. 存放指针需额外的存储空间
+ 2. 由于存取须通过缓冲区,待获得连接字后,才能找到下一物理块的地址,因而,仅适用于顺序存取
+6. 直接文件(散列文件)
+ 1. 通过计算记录的关键字建立与其物理存储地址之间的对应关系
+ 2. 这种变换通常采用散列法(hash法)
+ 3. 计算寻址结构可能出现”冲突“,即不同的关键字可能变换出相同的地址来,解决办法有拉链法、循环探查法、二次散列法、溢出区法等
+7. 索引文件
+ 1. 索引文件为每个文件建立了一张索引表,其中,每个表目包含一个记录的键(或逻辑记录号)及其存储地址
+ 2. 索引表的地址可由文件目录指出,查阅索引表找到相应记录键(逻辑记录号),然后获得数据存储地址
+ 3. 访问方式:
+ 1. 在文件存储器上分两个区:索引区和数据区
+ 2. 访问索引文件需两个步骤:查找索引表;获得记录物理地址
+ 3. 需要两次访问辅助存储器,若文件索引已预先调入主存储器,那么,就可以减少一次内外村信息交换
+ 4. 特点:
+ 1. 索引结构可以被认为是连接结构的一种扩展,除了具备连接文件的优点外,还客服了它只能作顺序存取的缺点,具有直接读写任意一个记录的能力,便于文件增删改
+ 2. 索引文件的缺点:增加了索引表的空间开销和查找时间
+ 5. 索引表组织
+ 1. 一级索引
+ 2. 两级索引
+ 3. 多级索引
+
+## 6 文件目录
+1. 实现文件的”按名存取“的关键数据结构
+2. 文件系统的基本功能之一就是负责文件目录的建立、维护和检索,要求编排的目录便于查找、防止冲突
+3. 文件目录需要永久保存,因此也组织成文件存放在磁盘上,称目录文件
+4. 一级目录结构
+ 1. 在操作系统中构造一张线性表,与每个文件的相关属性占用一个目录项,构成了一级目录结构
+ 2. 由于用户与文件众多,容易重名,不利记忆
+5. 二级目录结构
+ 1. 第一级为主文件目录,它用于管理所有用户文件目录,它的目录项登记了系统接受的用户的名字及该用户文件目录的地址
+ 2. 第二级为用户的文件目录,它为该用户的每个文件保存一个登记栏,其内容与一级目录的目录项相同
+ 3. 每一用户只允许查看自己的文件目录
+ 4. 特点
+ 1. 采用二级目录管理文件时,因为任何文件的存取都通过主文件目录,于是可以检查访问文件者的存取权限,避免一个用户未经授权就存取另一个用户的文件,使用户文件的私密性得到保证,实现了对文件的保密和保护
+ 2. 特别是不同用户具有同名文件时,由于各自有不同的用户文件目录而不会导致混乱
+ 3. 对于同一个用户而言,同样存在文件多、容易重名问题
+6. 树形目录结构
+ 1. 每一级目录可以登记下一级目录,也可以登记文件,从而,形成了层次文件目录结构
+ 2. 层次目录结构通常采用树形目录结构,它是一棵倒向的有根树,树根是根目录;从根向下,每一个树分叉是一个子目录;而树叶是文件
+ 3. 特点
+ 1. 较好地反映现实世界中具有层次关系的数据集合和较确切地反映系统内部文件的组织结构
+ 2. 不同文件可以重名,只要它们不位于同一末端的子目录中
+ 3. 易于规定不同层次或子树中文件的不同存取权限,便于文件的保护、保密和共享
+ 4. 文件定位
+ 1. 在树形目录结构中,一个文件的全名包括从根目录开始到文件为止,通路上遇到的所有子目录路径,又称为路径名
+ 2. 各子目录名之间用正斜线/(反斜线\)隔开
+ 3. 一个硬盘分区可以组织成一颗子树
+ 1. 每颗子树可以对应于一个逻辑盘符(Win)
+ 2. 把众多子树嫁接成一颗大树(UNIX)
+
+## 7 文件查找
+### 查找方法
+* 文件查找是文件目录管理的额重要工作,“按名存取”文件就是系统根据用户提供的文件路径名来搜索各级文件目录,找到该文件
+ 1. 从根目录查起(绝对路径名)
+ 2. 从"当前目录"查起(相对路径名),用'.'表示当前目录,'..'表示父目录
+ 3. 现代操作系统都设置有改变工作目录命令,即变更当前工作目录
+
+### 目录项查找
+1. 搜索具体目录项时,可以采用顺序查找法,依此扫描文件目录中的目录项,将目录项中的名字与欲查找的文件名相比较
+2. 优化方法
+ 1. 目录表项是按键的顺序编排,可以采用“二分查找法”
+ 2. "杂凑法“,把每个文件名经过变换函数变换成唯一的目录表表项
+
+### 文件目录处理
+1. 树形目录结构:当一个文件经过许多目录节点时,使用很不方便;系统在沿路径查找目录时,往往要多次访问文件存储器,使访问速度大大减慢
+2. 若把所有文件的目录都复制到主存,访问速度是加快了,但又增加了主存的开销
+3. 一种有效办法是把常用和正在使用的哪些文件目录复制进主存,这样,既不增加太多的主存开销,又可以明显减少目录查找时间
+
+### 活动文件表
+1. 系统可以为每个用户进程建立一张活动文件表,当用户使用一个文件之前,先通过”打开“操作,把该文件有关目录信息复制到指定主存区域,有关信息填入活动文件表,以建立用户进程和该文件索引的联系
+2. 当不再使用该文件时,使用”关闭“,切断用户进程和这个文件的联系,同时,若该目录已被修改过,则应更新辅存中对应的文件目录
+
+## 8 文件的安全与保护
+### 定义
+* 文件是计算机系统的重要资源,因此,要求文件系统具有保障文件安全的手段,提供文件保密的措施,有效地实现文件的共享
+### 文件共享:不同用户共同使用某些文件
+* 计算机用户完成共同任务所必需的
+* 好处:
+ 1. 减少大量重复性劳动
+ 2. 免除系统复制文件的工作
+ 3. 节省文件占用的存储空间
+ 4. 减少程序设计输入输出文件的次数
+
+* 并发控制
+ 1. 在允许文件共享的系统中,操作系统应提供手段实现对共享文件的同步控制
+ 2. 多个进程可能同时存取一个文件,如果它们同时进行读操作,操作系统应对文件进行公用控制
+ 3. 如果有进程进行写操作,例如,有两个进程,进程A要求修改文件,同时进程B要求读出同一文件中的数据,则操作系统给必须提供同步控制机制,以保证文件数据的完整性
+
+### 文件保护:防止文件被破坏
+1. 操作系统必须提供文件保护机制,有效实现文件的完整性
+2. 方法
+ 1. 文件副本
+ 1. 文件系统必须要有防止硬软件故障,保存信息完整性的能力。主要的实现机制就是文件副本
+ 2. 动态多副本技术
+ 1. 在多个介质上维持同一内容的文件,并且在更新内容时同时进行
+ 2. 需要增加设备费用和系统负载。一般适用于容量较小且较为重要的文件,例如不需更新的系统文件及专用文件,当文件发生故障时只要切换到备用设备就可以
+ 3. 转储、备份与恢复
+ 1. 文件转储:定时把文件复制转储到其他介质上,当某介质上出现故障时,复原转储文件
+ 2. 转储方式
+ 1. 一定时间间隔或一个单位处理结束时,系统自动复写更新过的文件和数据
+ 2. 每天或每周把文件信息全部复写一遍,需要时再通过装入转储文件来恢复系统,诸如BACKUP、RESTORE等命令
+ 2. 文件存取矩阵与文件读取表
+ 1. 系统为每个用户设置访问每个文件对象的存取属性
+ 2. 系统的全部用户对全部文件的存取属性就组成的一个二维矩阵,称为存取控制矩阵
+ 3. 由于操作系统拥有很多用户和众多文件,存取控制矩阵是一个稀疏矩阵,可以将其简化为一张存取控制表
+ 4. 每行包括:用户、文件、存取属性
+ 5. 存取控制表仅登记那些对文件拥有存取属性的部分
+ 6. 基于存取控制矩阵/表的文件保护
+ 1. 存取属性:可以有访问、读、写、执行、创建、删除、授权等等
+ 2. 系统通过查阅(矩阵/表)核对用户对文件的存取权限
+ 3. 文件属主使用GRANT、REVOKE等命令进行授权,甚至把授权权转授给他信任的用户
+ 4. 系统管理用户(超级用户)等同于文件属主权限,并获得对系统文件的授权访问权权限
+ 3. 文件属性
+ 1. 存取控制表的一种简化方法是用户分类,再针对每类用户规定文件属性
+
+ 2. 用户分类:属主、合作者、其他
+
+ 3. 文件属性:读、写、执行、...
+
+ 4. 文件属性可以放在文件目录项中,管理大为简化
+
+ 5. 用户使用文件时,通过核对文件属性,实现保护
+
+ 6. 文件属性的例
+ 1. chmod命令可以改变文件属性
+ 2. chown命令用于变更文件属主
+ 3. chgrp命令用户变更用户伙伴
+
+ | Name | 读 | 写 | 执行 |
+ | -------- | ---- | ---- | ---- |
+ | 文件主 | 1 | 1 | 0 |
+ | 伙伴 | 1 | 0 | 0 |
+ | 其他用户 | 1 | 0 | 0 |
+
+### 文件保密:防止文件及其内容被其他用户窃取
+1. 措施
+ 1. 隐蔽文件目录
+ 2. 设置口令
+ 3. 使用密码
+
+## 9 文件的使用
+### 用户通过两类接口与文件系统联系
+1. 与文件有关的操作命令。UNIX中,cat、cd、cp、find、mv、rm、mkdir、rmdir等等
+2. 提供给用户程序使用的文件类系统调用,基本文件类系统调用:建立、打开、读/写、定位、关闭、撤销
+ 1. 建立文件
+ 1. 用于创建一个文件
+ 2. 所需参数:文件名、设备类(号)、文件属性及存取控制信息
+ 3. 处理流程:在相应设备上建立一个文件目录项,为文件分配第一个物理块,在活动文件表中申请一个项,登记有关目录信息,并返回一个文件句柄
+ 2. 撤销文件
+ 1. 用于删除一个文件
+ 2. 所需参数:文件名、设备类(号)
+ 3. 处理流程:若文件没有关闭,先关闭文件;若为共享文件,进行联访处理;在目录文件中删除相应目录项;释放文件占用的文件存储空间
+ 3. 打开文件
+ 1. 用于建立起文件和用户进程之间的使用联系
+ 2. 所需参数:文件名、设备类(号)、打开方式
+ 3. 处理流程:在主存活动文件表中申请一个项,返回一个文件句柄;根据文件名查找目录文件,把目录信息复制到活动文件表相应栏;若打开的是共享文件,则应有相应处理
+ 4. 关闭文件
+ 1. 用于结束一个文件的读写
+ 2. 所需参数:文件句柄
+ 3. 处理流程:将活动文件表中该文件的”当前使用用户数“减1;完成”推迟写";若活动文件表目内容已被改过,则应先将表目内容写回文件存储器上相应表目中,以使文件目录保持最新状态
+ 5. 读/写文件
+ 1. 用于读写文件
+ 2. 所需参数:文件句柄、用户数据区地址、读写的记录或字节个数
+ 3. 处理流程:按文件句柄从活动文件表中找到该文件的目录项信息;根据目录项指出的该文件的逻辑和物理组织方式,把相关逻辑记录转换成物理块
+ 6. 定位文件
+ 1. 用于调整所打开文件的读写指针位置
+ 2. 所需参数:文件句柄、定位指针
+
+## 10 辅存空间管理
+1. 磁盘等大容量辅存空间被OS及许多用户共享,用户进程运行期间常常要建立和删除文件,OS应能自动管理和控制辅存空间
+2. 随着用户文件不断建立和撤销,文件存储空间会出现许多“碎片”
+3. OS解决“碎片”的办法是整理“碎片”;在整理过程中,往往对文件重新组织,让其存放在连续存储区中
+4. 分配方式
+ 1. 连续分配:存放在辅存空间连续存储区中(连续的物理块号)
+ 1. 优点:顺序访问时速度快,管理较为简单,但为了获得足够大的连续存储区,需定时进行“碎片”整理
+ 2. 非连续分配:动态分配给若干扇区或簇(几个连续扇区),不要求连续
+ 1. 优点:辅存空间管理效率高,便于文件动态增长和收缩
+5. 空闲块的管理:位示图
+ 1. 使用若干字节构成一张表,表中每一字位对应一个物理块,字位的次序与块的相对次序一致。字位为“1”表示相应块已占用,字位为“0”状态表示该块空闲
+ 2. 主要优点:可以把位示图全部或大部分保存在主存中,再配合现代计算机都具有的位操作指令,可实现高速物理块分配和去配
+ 3. 空闲块成组连接法
+ 1. 分配算法
+ 1. IF 空闲块数=1 THEN
+ 1. IF 第1个单元=0 THEN 等待
+ 2. ELSE 复制第1个单元对应块到专用块并分配之
+ 2. ELSE 分配第(空闲块数)个单元对应块,空闲块数-1
+ 2. 归还算法
+ 1. IF 空闲块数<100 THEN
+ 1. 专用块的空闲块数+1,第(空闲块数)个单元置归还块号
+ 2. ELSE 复制专用块到归还块,专用块的空闲块数置1,第1单元置归还块号
+
+## 11 文件系统的实现层次
+1. 用户接口:接受用户发来的系统调用,进行语法检查,进入逻辑文件控制子系统
+2. 逻辑文件控制子系统:根据文件路径名,搜索文件目录,建立活动文件表,根据文件结构和存取方法,把逻辑记录转换成相对物理块号和块内相对地址
+3. 文件保护子系统:识别调用者的身份,验证存取权限,判定本次文件操作的合法性
+4. 物理文件控制子系统:实现缓冲区管理,根据物理结构,将相对物理块号转换为实际物理块号,负责文件存储空间的分配,生成I/O控制系统的调用形式
+5. I/O控制子系统:执行具体的物理块I/O操作
diff --git a/操作系统/8 并发程序设计.md b/操作系统/8 并发程序设计.md
new file mode 100644
index 00000000..b98805a7
--- /dev/null
+++ b/操作系统/8 并发程序设计.md
@@ -0,0 +1,611 @@
+# 并发程序设计
+
+## 1 顺序程序设计
+1. 程序是实现算法的操作(指令)序列
+2. 每个程序在处理器上执行是严格有序的,称为程序执行的内部顺序性
+3. 程序设计的一般习惯是顺序程序设计
+ 1. 把一个具体问题的求解过程设计成一个程序或者若干严格顺序执行的程序序列,称为程序执行的外部顺序性
+4. 特性:
+ 1. 程序执行的顺序性:程序指令执行是严格按序的
+ 2. 计算环境的封闭性:程序运行时如同独占受操作系统保护的资源
+ 3. 计算结果的确定性:程序执行结果与执行速度和执行时段无关
+ 4. 计算过程的可再见性:程序对相同数据集的执行轨迹是确定的
+
+## 2 进程的并发执行
+1. 多道程序设计让多个程序同时进入内存去竞争处理器以获得运行机会
+2. OS允许计算机系统在一个时间段内存在多个正在运行的进程,即允许多个进程并发执行
+3. OS保证按照“顺序程序设计”方法编程的程序在并发执行时不受影响,如同独占计算机
+4. 这些按照顺序程序设计思想编程的进程在OS中并发执行属于无关的并发进程
+
+## 3 处理器利用率计算
+1. 顺序程序设计:input(78s)、process(52s)、output(20s),52/(78+52+20)=35%
+2. 并发程序设计:时间同上,while(1){input,send}; while(1){receive,process,send}; while(1){receive,output},(52*n)/(78*n+52+20)=67%,n趋近于无穷大
+
+## 4 并发程序设计
+### 概念
+* 把一个具体问题求解设计成若干个可同时执行的程序模块的方法
+### 特性:
+1. 并发性:多个进程在多道程序系统中并发执行或者在多处理器系统中并行执行:提高了计算效率
+2. 共享性:多个进程共享软件资源
+3. 交往性:多个进程并发执行时存在制约:增加了程序设计的难度
+
+### 无关与交往的并发进程
+1. 无关:一组并发进程分别在不同变量集合上运行,一个进程的执行与其他并发进程的进展无关
+2. 交往:一组并发进程共享某些变量,一个进程的执行可能影响其他并发进程的结果
+
+### 与时间有关的错误
+1. 对于一组交往的并发进程,执行的相对速度无法相互控制
+2. 如果程序设计不当,可能出现各种“与时间有关的”错误
+3. 表现一:结果错误;表现二:永远等待
+
+### 进程互斥与进程同步
+1. 交互的并发进程在执行时必须进行制约,才能保证得到合理的结果
+2. 进程互斥:并发进程之间因相互争夺独占性资源而产生的竞争制约关系
+3. 进程同步:并发进程之间为完成共同任务基于某个条件来协调执行先后关系而产生的协作制约关系
+
+### 互斥与临界区
+1. 临界资源:互斥共享变量所代表的资源,即一次只能被一个进程使用的资源
+2. 临界区:并发进程中与互斥共享变量相关的程序段
+ 1. 确定临界资源 share
+ 2. 确定临界区 region do
+ 3. 两个进程的临界区有相同的临界资源,就是相关的临界区,必须互斥进入
+ 4. 两个临界区不相关,进入就没有限制
+ 5. 临界区管理的三个要求
+ 1. 一次至多允许一个进程停留在相关的临界区内
+ 2. 一个进程不能无限止地停留在临界区内
+ 3. 一个进程不能无限止地等待进入临界区
+ 6. 临界区管理
+ 1. 同时进入临界区
+ ```c
+ process P1
+ begin
+ while inside2 do [ ];
+ inside1 := true;
+ 临界区;
+ inside1 := false;
+ end;
+
+ process P2
+ begin
+ while inside1 do [ ];
+ inside2 := true;
+ 临界区;
+ inside2 := false;
+ end;
+ ```
+ 2. 同时等待进入临界区
+ ```c
+ process P1
+ begin
+ inside1 := true;
+ while inside2 do [ ];
+ 临界区;
+ inside1 := false;
+ end;
+
+ process P2
+ begin
+ inside2 := true;
+ while inside1 do [ ];
+ 临界区;
+ inside2 := false;
+ end;
+ ```
+ 7. 解决思路
+ ```c
+ // 测试锁
+ TS(x) {
+ if (x==false) {x=true;return true;
+ } else return false;
+ }
+ Boolean lock;
+ lock=false; // 临界区可用
+ process Pi {
+ Boolean pi;
+ repeat pi=TS(lock) until pi; // 循环请求锁
+ 临界区
+ lock=false; // 解锁
+ }
+ // 交换锁
+ swap(a, b){temp=a;a=b;b=temp;}
+ Boolean lock;
+ lock=false; // 临界区可用
+ process Pi {
+ Boolean pi;
+ pi=true;
+ repeat swap(lock, pi) until !pi; // 循环建立锁
+ 临界区;
+ lock=false; // 解锁
+ }
+ ```
+ 8. 实现临界区管理的硬件设施
+ 1. TS和swap指令均是忙式等待,效率低
+ 2. 简单的解决办法是在进出临界区时开关中断,这样临界区执行就不会中断了,执行就有原子性。关中断;临界区;开中断
+ 3. 操作系统原语就采用这种实现思路
+ 4. 但是,临界区的指令长度应该是短小精悍,这样才能保证系统效率
+ 5. 不建议用户程序使用,滥用是可怕的!
+3. 多个并发进程访问临界资源时,存在竞争制约关系。如果两个进程同时停留在相关的临界区内就会出现与时间相关的错误
+
+## 5 PV操作与进程互斥
+### 问题
+1. TS或swap指令管理临界区,采用忙式轮询,效率低
+2. 关开中断管理临界区,不便交给用户程序使用
+
+### 信号量的构思
+1. 一种可动态定义的软件资源:信号量
+ 1. 核心数据结构:等待进程队列
+ 2. 信号量声明:资源报到,建立队列
+ 3. 申请资源的原语:若申请不到,调用进程入队等待
+ 4. 归还资源的原语:若队列中有等待进程,需释放
+ 5. 信号量撤销:资源注销,撤销队列
+2. 记录型信号量:一种带数值的软资源
+ ```c
+ typedef struct semaphore {
+ int value; // 信号量值
+ struct pcb *list; // 信号量等待进程队列指针
+ }
+ ```
+ 1. 每个信号量建立一个等待进程队列
+ 2. 每个信号量相关一个整数值
+ 1. 正值表示资源可复用次数
+ 2. 0值表示无资源且无进程等待
+ 3. 负值表示等待队列中进程个数
+ 3. P、V操作原语
+ ```c
+ procedure P(semaphore:s) {
+ s -= 1; // 信号量-1
+ if (s<0) W(s); // 若信号量小于0,则调用进程被置成等待信号量s的状态
+ }
+ procedure V(semaphore:s) {
+ s += 1; // 信号量+1
+ if (s<=0) R(s); // 若信号量小于等于0,则释放一个等待信号量s的进程
+ }
+ ```
+ 4. PV操作解决进程互斥问题框架
+ ```c
+ semaphore s;
+ s=1;
+ begin
+ process Pi {
+ ......
+ P(s);
+ 临界区;
+ V(s);
+ ......
+ }
+ end;
+ ```
+ 5. PV操作解决进程同步问题
+ 1. 进程同步:并发进程为完成共同任务基于某个条件来协调执行先后关系而产生的协作制约关系
+ 2. 一个进程的执行等待来自于其他进程的消息
+ 3. 解决的基本思路:
+ 1. 定义一个信号量:其数值代表可用消息数
+ 2. 等待消息进程:执行P,无消息则等待
+ 3. 发出消息进程:执行V,有等待进程则释放
+ 4. 1生产者1消费者1缓冲区问题
+ 1. 生产者和消费者共享缓冲区
+ 2. 缓冲区有空位时,生产者可放入产品,否则等待
+ 3. 缓冲区有产品时,消费者可取出产品,否则等待
+ ```c
+ Int B;
+ process producer
+ begin
+ L1:
+ produce a product;
+ B = product;
+ goto L1;
+ end;
+
+ process consumer
+ begin
+ L2:
+ product = B;
+ consume a product;
+ goto L2;
+ end;
+ // 正确执行顺序:P→(同步关系1:等待产品)C→(同步关系2:等待缓冲)P→C→P→C...
+
+ // 信号量仅仅解决信号传递数据传送需要共享缓冲区
+ ```
+ 4. 解决思路:
+ 1. 同步关系1:消费者一开始在等待产品到来,考虑设置一个信号量(等待产品);一开始无产品,初值为0
+ 2. 同步关系2:消费者则在等待缓冲区中有空位,也可设置一个信号量(等待缓冲区);一开始缓冲区有空位,初值为1
+ ```c
+ // PV解决1生产者1消费者1缓冲区问题
+ Int B; // 共享缓冲区
+ Semaphore sput; // 可以使用的空缓冲区
+ Semaphore sget; // 缓冲区内可以使用的产品数
+ sput = 1; // 缓冲区内允许放入一件产品
+ sget = 0; // 缓冲区内没有产品
+ process producer {
+ L1:
+ produce a product;
+ P(sput);
+ B = product;
+ V(sget);
+ goto L1;
+ }
+
+ process consumer {
+ L2:
+ P(sget);
+ product = B;
+ V(sput);
+ consume a product;
+ goto L2;
+ }
+
+ // PV解决1生产者1消费者N缓冲区问题
+ Int B[k]; // 共享缓冲区队列
+ Semaphore sput; // 可以使用的空缓冲区
+ Semaphore sget; // 缓冲区内可以使用的产品数
+ sput = k; // 缓冲区内允许放入k件产品
+ sget = 0; // 缓冲区内没有产品
+ Int putptr, getptr; // 循环队列指针
+ putptr = 0; getptr = 0;
+ process producer_i {
+ L1:
+ produce a product;
+ P(sput);
+ B[putptr] = product;
+ putptr = (putptr+1) mod k;
+ V(sget);
+ goto L1;
+ }
+
+ process consumer_j {
+ L2:
+ P(sget);
+ product = B[getptr];
+ getptr = (getptr+1) mod k;
+ V(sput);
+ consume a product;
+ goto L2;
+ }
+
+ // PV解决N生产者N消费者N缓冲区问题
+ Int B[k]; // 共享缓冲区队列
+ Semaphore sput; // 可以使用的空缓冲区
+ Semaphore sget; // 缓冲区内可以使用的产品数
+ sput = k; // 缓冲区内允许放入k件产品
+ sget = 0; // 缓冲区内没有产品
+ Int putptr, getptr; // 循环队列指针
+ putptr = 0; getptr = 0;
+ s1, s2:semaphore; // 互斥使用putptr,getptr
+ s1 = 1;s2 = 1;
+ process producer_i {
+ L1:
+ produce a product;
+ P(sput);
+ P(s1);
+ B[putptr] = product;
+ putptr = (putptr+1) mod k;
+ V(s1);
+ V(sget);
+ goto L1;
+ }
+
+ process consumer_j {
+ L2:
+ P(sget);
+ P(s2);
+ product = B[getptr];
+ getptr = (getptr+1) mod k;
+ V(s2);
+ V(sput);
+ consume a product;
+ goto L2;
+ }
+ ```
+ ```c
+ // 苹果橘子问题
+ Int plate;
+ Semaphore sp; // 盘子里可以放几个水果
+ Semaphore sg1; // 盘子里有桔子
+ Semaphore sg2; // 盘子里有苹果
+ sp = 1; // 盘子里允许放入一个水果
+ sg1 = 0; // 盘子里没有桔子
+ sg2 = 0; // 盘子里没有苹果
+ process father {
+ L1: 削一个苹果;
+ P(sp);
+ 把苹果放入plate;
+ V(sg2);
+ goto L1;
+ }
+
+ process mother {
+ L2: 剥一个桔子;
+ P(sp);
+ 把桔子放入plate;
+ V(sg1);
+ goto L2;
+ }
+
+ process son {
+ L3: P(sg1);
+ 从plate中取桔子;
+ V(sp);
+ 吃桔子;
+ goto L3;
+ }
+
+ process daughter {
+ L4: P(sg2);
+ 从plate中取苹果;
+ V(sp);
+ 吃苹果;
+ goto L4;
+ }
+ ```
+
+## 5 管程概念的提出
+1. 管程试图抽象相关并发进程对共享变量访问,以提供一个友善的并发程序设计开发环境
+2. 管程是由若干公共变量及其说明和所有访问这些变量的过程所组成
+3. 管程把分散在各个进程中互斥地访问公共变量的那些临界区集中起来管理,管程的局部变量只能由该管程的过程存取
+4. 进程只能互斥地调用管程中的过程
+5. 管程的条件变量
+ 1. 条件变量(condition variables):当调用管程过程的进程无法运行时,用于阻塞进程的信号量
+ 2. 同步原语wait:当一个管程过程发现无法继续时(如发现没有可用资源时),它在某些条件变量上执行wait,这个动作引起调用进程阻塞
+ 3. 同步原语signal:用于释放在条件变量上阻塞的进程
+6. 管程过程执行中signal的处理问题
+ 1. 当使用signal释放一个等待进程时,可能出现两个进程同时停留在管程内。解决办法:
+ 1. 执行signal的进程等待,直到被释放进程退出管程或等待另一个条件
+ 2. 被释放进程等待,直到执行signal的进程退出管程或等待另一个条件
+ 2. 霍尔采用了第一种办法
+ 3. 汉森选了二者的折中,规定管程过程所执行的signal操作是过程体的最后一个操作
+
+## 6 霍尔管程的实现方法
+
+1. 使用signal释放一个等待进程时,霍尔管程让执行signal的进程等待,直到被释放进程退出管程或等待另一个条件
+2. 霍尔管程基于PV操作原语实现
+ 1. Wait和signal可以是程序过程
+ 2. 可以用语言机制实现霍尔管程
+ ```c
+ // 互斥调用霍尔管程的信号量
+ TYPE interf=RECORD
+ mutex: semaphore; // 调用管程过程前使用的互斥信号量
+ next: semaphore; // 发出signal的进程挂起自己的信号量
+ next_count: integer; // 在next上等待的进程数
+ END;
+ // 互斥调用霍尔管程的框架
+ P(IM.mutex);
+ <过程体>
+ if IM.next_cout > 0 then V(IM.next);
+ else V(Im.mutex);
+ // 霍尔管程的条件变量
+ x_sem: semaphore; // 与资源相关的信号量
+ x_count: integer; // 在x_sem上等待的进程数
+ // 霍尔管程的wait进程
+ procedure wait(var x_sem: semaphore, var x_count: integer, var IM: interf);
+ begin
+ x_count += 1;
+ if IM.next_count > 0 then V(IM.next);
+ else V(IM.mutex);
+ P(x_sem);
+ x_count -= 1;
+ end;
+ // 霍尔管程的signal过程
+ procedure signal(var x_sem: semaphore, var x_count: integer, var IM: interf);
+ begin
+ if x_count > 0 then begin
+ IM.next_count += 1;
+ V(x_sem);
+ P(IM.next); // 进入等待调用管程的队列
+ IM.next_count -= 1;
+ end;
+ end;
+
+ // 哲学家问题
+ TYPE dining_philosophers = MONITOR
+ var state: array[0..4] of (thinking, hungry, eating);
+ s: array[0..4] of semaphore;
+ s_count: array[0..4] of integer;
+ define pickup, putdown;
+ use wait, signal;
+ procedure test(k: 0..4) P
+ if state[(k-1) mod 5] <> eating and state[k]=hungry
+ and state[(k+1) mod 5] <> eating then
+ {state[k] := eating; signal(s[k],s_count[k],IM);}
+ }
+
+ procedure pickup(i:0..4) {
+ state[i] := hungry;
+ test(i);
+ if state[i] <> eating
+ then wait(s[i], s_count[i], IM);
+ }
+
+ procedure putdown(i:0..4 {
+ state{i]:=thinking;
+ test((i-1) mod 5);
+ test((i+1) mod 5);
+ }
+
+ begin
+ for i:=0 to 4 do
+ state[i] := thinking;
+ end;
+
+ begin
+ process philosopher_i() {
+ L:thinking();
+ P(IM.mutex);
+ dining_philosophers.pickup(i);
+ if IM.next_count > 0 then V(IM.next); else V(IM.mutex);
+ eating();
+ P(IM.mutex);
+ dining_phi;osophers.putdown(i);
+ if IM.next_count > 0 then V(IM.next); else V(IM.mutex);
+ goto L;
+ }
+ end;
+
+ // 读者写者问题
+ TYPE read-writer = MONITOR
+ var Rc, Wc: integer; R, W:semaphore; rc, wc: integer;
+ define start_read, end_read, start_writer, end_writer;
+ use wait, signal, check, release;
+ begin rc:=0;wc:=0;Rc:=0;Wc:=0;R:=0;W:=0; end;
+
+ procedure start_read;
+ begin
+ if wc > 0 then wait(R,Rc,IM);
+ rc += 1;
+ signal(R, Rc, IM); // 连续释放读者
+ end;
+
+ procedure end_read;
+ begin
+ rc += 1;
+ if rc = 0 then signal(W, Wc,IM);
+ end;
+
+ procedure start_write;
+ begin
+ wc += 1;
+ if rc > 0 or wc > 1 then wait(W, Wc, IM);
+ end;
+
+ procedure end_write;
+ begin
+ wc += 1;
+ if wc > 0 then signal(W,Wc,IM);
+ else signal(R,Rc,IM);
+ end;
+ ```
+
+## 7 进程通信的概念
+
+1. 交往进程通过信号量操作实现进程互斥和同步,这是一种低级通信方式
+2. 进程有时还需交换更多的信息(如把数据传送给另一个进程),可以引进高级通信方式——进程通信机制,实现进程间用信件来交换信息
+3. 进程通信扩充了并发进程的数据共享
+4. 进程直接通信
+ 1. 发送或接收信件的进程指出信件发给谁或从谁那里接收信件
+ 1. send(P,信件):把信件发送给给进程P
+ 2. receive(Q,信件);从进程Q接收信件
+5. 进程间接通信
+ 1. 发送或接收信件通过一个信箱来进行,该信箱有唯一标识符
+ 2. 多个进程共享一个信箱
+ 1. send(A,信件):把信件传送到信箱A
+ 2. receive(A,信件):从信箱A接收信件
+ 3. 间接通信的信箱
+ 1. 存放信件的存储区域,每个信箱可以分成信箱特征和信箱体两部分
+ 1. 信箱特征指出信箱容量、信件格式、指针等
+ 2. 信箱体用来存放信件,信箱体分成若干个区,每个区可容纳一封信
+6. 发送信件原语的处理流程
+ 1. 若指定的信箱未满,则把信件送入信箱中指针所指示的位置,释放等待该信箱中信件的等待者;否则,发送信件者被置成等待信箱的状态
+7. 接收信件原语的处理流程
+ 1. 若指定信箱中有信件,则取出一封信件,释放等待信箱的等待者;否则,接收信件者被置成等待信箱中信件的状态
+
+## 8 基于流的进程通信
+
+1. 多个进程使用一个共享的消息缓冲区(管道、多路转接器、套接字)
+2. 一些进程往消息缓冲区中写入字符流(send/write)
+3. 一些进程从消息缓冲区中读出字符流(receive/read)
+4. 信息交换单位基于字符流,长度任意
+
+## 9 远程过程调用RPC
+
+1. 采用客户/服务器计算模式
+2. 服务器进程提供一系列过程/服务,供客户进程调用
+3. 客户进程通过调用服务器进程提供的过程/服务获得服务
+4. 考虑到客户计算机和服务器计算机的硬件异构型,外部数据表示XDR被引入来转换每台计算机的特殊数据格式为标准数据格式
+
+## 10 死锁的产生
+
+### 定义
+1. 允许多个进程并发执行共享系统资源时,系统必须要提供同步机制和进程通信机制。然而,对这种机制使用不当的话,可能会出现进程永久被阻塞的现象。例如,两个进程分别等待对方占有的一个资源,于是两者都不能执行而处于永远等待,这种现象称为“死锁”
+
+### 死锁:每一个进程都在等待被另一个进程所占有的、不能抢占的资源
+1. 存在n个进程P1,P2,...,Pn
+2. 进程Pi因为申请不到资源Ri而处于等待状态
+3. 而Ri又被Pi+1占有,Rn被P1占有
+4. 显然,这n个进程的等待状态永远不能结束,这n个进程就处于死锁状态
+
+### 产生
+1. 竞争资源产生死锁
+2. PV操作使用不当产生死锁
+3. 同类资源分配不当引起死锁
+ 1. 若系统中有m个资源被n个进程共享,当每个进程都要求K个资源,而$m< n\times(K-1)+1$时,如果分配不当就可能引起死锁
+4. 对临时性资源使用不加限制引起死锁
+ 1. 在进程通信时使用的信件可以看作是一种临时性资源,如果对信件的发送和接收不加限制的话,则可能引起死锁
+5. 产生的必要条件
+ 1. 互斥条件:进程应互斥使用资源,任一时刻一个资源仅为一个进程独占
+ 2. 占有和等待条件:一个进程请求资源得不到满足而等待时,不释放已占有的资源
+ 3. 不剥夺条件:任一进程不能从另一进程那里抢夺资源
+ 4. 循环等待条件:存在一个循环等待链,每一个进程分别等待它前一个进程所持有的资源
+
+### 解决办法
+#### 产生死锁因素:
+1. 系统拥有的资源数量
+2. 资源分配的策略
+3. 进程对资源的使用要求以及并发进程的推进顺序
+
+#### 三个方面解决死锁问题
+1. 死锁防止
+ 1. 破坏四个必要条件之一
+ 2. 破坏第一个条件,把独占型资源改造成共享性资源,使资源可同时访问而不是互斥使用。但对许多资源无法做到
+ 3. 破坏第三个条件,采用剥夺式调度方法,但剥夺式调度方法目前只适用于对主存资源和处理器资源的分配,而不适用于所有资源
+ 4. 破坏第二个条件,采用静态分配
+ 1. 静态分配:一个进程必须在执行前就申请它所要的全部资源,并且直到它索要的资源都得到满足之后才开始执行
+ 2. 所有并发执行的进程要求的资源总和不超过系统拥有的资源数
+ 3. 进程在执行过程中不再申请资源,所以就破坏了第二个条件
+ 5. 破坏第四个条件,层次分配
+ 1. 层次分配将资源分成多个层次
+ 2. 一个进程得到某一层的一个资源后,它只能再申请在较高层的资源
+ 3. 当一个进程要释放某层的一个资源时,必须先释放所占用的较高层的资源
+ 4. 当一个进程获得了某一层的一个资源后,它想再申请该层中的另一个资源,那么必须先释放该层中的已占资源
+2. 死锁避免
+ 1. 当不能防止死锁的产生时,如果能掌握并发进程中与每个进程有关的资源申请情况,仍然可以避免死锁的发生
+ 2. 只需要在位申请者分配资源前先测试系统状态,若把资源分配给申请者会产生死锁的话,则拒绝分配,否则接收申请,为它分配资源
+ 3. 银行家算法:借钱给有偿还能力的客户
+ 1. 系统首先检查申请者对资源的最大需求量,如果现存的资源可以满足它的最大需求量时,就满足当前的申请
+ 2. 换言之,仅仅在申请者可能无条件地归还它所申请的全部资源时,才分配资源给它
+ 3. 例:
+ 1. 假设系统有三个进程P、Q、R,系统只有一类资源共10个。分配情况:
+ 1. P:占有4个,还需申请4个
+ 2. Q:占有2个,还需申请2个
+ 3. R:占有2个,还需申请7个
+ 2. 现在总共占用了8个资源,只能再分配个两个资源。所以先分配给Q,等Q完成之后,就有4个资源,继续分配给P,等P完成之后,就有8个资源,最后给R
+3. 死锁检测和恢复
+ 1. 对资源的分配不加限制,但系统定时运行一个“死锁检测”程序,判定系统内是否已出现死锁,若检测到死锁则设法加以解除
+ 2. 检测:
+ 1. 可设置两张表格来记录进程使用资源的情况
+ 1. 等待资源表记录每个被阻塞进程等待的资源
+ 2. 占用资源表记录每个进程占有的资源
+
+ 2. 进程申请资源时,先查该资源是否为其他进程所占用;若资源空闲,则把该资源分配给申请者且登入占用表;否则,则登入进程等待资源表
+
+ 3. 死锁检测程序定时检测这两张表,若有进程Pi等待资源rk,且rk被进程Pj占用,则说明Pi和Pj具有“等待占用关系”,记为W(Pi,Pj)
+
+ 4. 死锁检测程序反复检测这两张表,可以列出所有的“等待占用关系”
+
+ 5. 如果出现W(Pi,Pj),W(Pj,Pk),...,W(Pm,Pn),W(Pn,Pi)时,显然,系统中存在一组循环等待资源的进程:Pi,Pj,Pk,...,Pm,Pn,也就是说出现了死锁
+
+ 6. 两张表可以用一个矩阵A表示
+
+ | 进程/$A[b_{ij}]$/进程 | P1 | P2 | ... | Pn |
+ | --------------------- | ---- | ---- | ---- | ---- |
+ | P1 | b11 | b12 | ... | b1n |
+ | P2 | b21 | b22 | ... | b2n |
+ | ... | ... | ... | ... | ... |
+ | Pn | bn1 | bn2 | ... | bnn |
+
+ 其中b_ij=1表示当Pi等待被Pj占用的资源时,=0表示Pi与Pj不存在等待占用关系时
+
+ 7. 算法
+ ```c
+ // Warshall的传递闭包算法检测是否有死锁发生
+ // 即对矩阵A构造传递闭包A*[bij]
+ for k:= 1 to n do
+ for i: 1 to n do
+ for j:= 1 to n do
+ bij:= bij∪(bij∩bkj)
+ ```
+
+#### 死锁检测后的解决办法
+1. 采用重新启动进程执行的办法,恢复工作应包含重启动一个或全部进程,以及从哪一点开始重启动
+2. 全部卷入死锁从头开始启动,但这样的代价相当大
+3. 进程执行过程中定时设置校验点,从校验点开始重执行
+4. 中止一个卷入死锁的进程,以后重执行
diff --git a/操作系统/9 其他.md b/操作系统/9 其他.md
new file mode 100644
index 00000000..6e76eff8
--- /dev/null
+++ b/操作系统/9 其他.md
@@ -0,0 +1,123 @@
+# 其他
+
+## 1 计算机系统层级(由上到下):
+
+1. 应用——用户
+2. 语言处理——应用程序员的视图
+3. 操作系统——语言处理程序设计者的视图
+4. 计算机硬件——操作系统设计者的视图
+
+## 2 存储程序计算机特点
+
+1. 以运算单元为中心,控制流由指令流产生
+2. 采用存储程序原理,面向主存组织数据流
+3. 主存是按地址访问、线性编址的空间
+4. 指令由操作码和地址码组成
+5. 数据以二进制编码
+
+## 3 程序员的计算机系统视图(由下到上)
+
+1. 计算机硬件系统——机器指令(语言)
+ 1. 机器指令是计算机系统执行的基本命令,是中央处理器执行的基本单位
+ 2. 指令由一个或多个字节组成,包括操作码字段、一个或多个操作数地址字段、以及一些表征机器状态的状态字以及特征码
+ 3. 指令完成各种算术逻辑运算、数据传输、控制流跳转
+ 4. 分类
+ 1. 特权指令:只能被操作系统内核使用的指令
+ 2. 非特权指令:能够被所有程序使用的指令
+ 3. 用户程序并非能够使用全部的机器指令,那些与计算机核心资源相关的特殊指令会被保护
+2. 操作系统与实用程序——扩展机器指令
+ 1. 资源管理:机器语言+广义指令(扩充了硬件资源管理)
+ 2. 文件系统:机器语言+系统调用(扩充了信息资源管理)
+3. 数据库管理系统——数据库语言
+4. 语言处理程序——高级语言(面向问题的语言)
+5. 支撑软件——程序员(涵盖以上)
+
+## 4 计算机程序执行过程:
+
+1. 高级语言源程序通过转换程序,再通过编译程序和解释程序,变成目标代码程序
+2. 汇编语言源程序通过汇编程序,变成目标代码程序
+3. 目标代码程序通过连接程序,变成可执行程序,通过装入程序,变成内存执行程序
+4. 同时进入数据库管理系统和操作系统,数据库管理系统同时进入文件系统和设备管理(属于操作系统)
+
+P.S.
+操作系统
+1. 文件系统
+2. 设备管理
+3. 内存管理
+4. 进程管理
+
+## 5 指令执行过程
+
+1. CPU根据PC取出指令,放入IR,并对指令译码,然后发出各种控制命令,执行微操作系列,从而完成一条指令的执行
+2. 步骤
+ 1. 取指:根据PC从存储器或高速缓冲存储器中取指令到IR
+ 2. 解码:解译IR中的指令来绝对其执行行为
+ 3. 执行:连接到CPU部件,执行运算,产生结果并写回,同时在CC里设置运算结论标志;跳转指令操作PC,其他指令递增PC值。
+
+P.S.
+在一条指令进行解码操作时,另一条指令可以开始取指;在进行执行操作时,另一条可以在执行解码,而第三条可以开始取指
+
+多道程序同时计算:CPU速度与I/O速度不匹配的矛盾非常突出。只有让多道程序同时进入内存争抢CPU运行,才可以使得CPU和外围设备充分并行,从而提高计算机系统的使用效率
+
+## 6 多道程序设计
+### 概念
+
+* 指让多个程序同时进入计算机的主存储器进行计算
+
+### 特点:
+
+1. CPU与外部设备充分并行
+2. 外部设备之间充分并行
+3. 发挥CPU的使用效率
+4. 提高单位时间的算题量
+
+### 实现:
+
+1. 进程:进入内存执行的程序建立管理实体
+2. OS应能管理与控制进程程序的执行
+3. OS协调管理各类资源在进程间的使用
+ 1. 处理器的管理和调度
+ 2. 主存储器的管理和调度
+ 3. 其他资源的管理和调度
+
+### 实现要点:
+
+1. 如何使用资源:调用操作系统提供的服务例程(如何陷入操作系统)
+2. 如何复用CPU:调度程序(在CPU空闲时让其他程序运行)
+3. 如何使CPU与I/O设备充分并行:设备控制器与通道(专用的I/O处理器)
+4. 如何让正在运行的程序让出CPU:中断(中断正在执行的程序,引入OS处理)
+
+## 7 操作系统的人机交互
+
+1. 交互设备
+ 1. 传统的终端设备
+ 2. 新型的模式识别设备
+2. 发展
+ 1. 交互式控制方式
+ 1. 行命令控制方式:1960年代开始使用
+ 2. 全屏幕控制方式:1970年代开始使用
+ 2. 强调人而不是技术是人机交互的中心
+ 3. WIMP界面
+ 1. 窗口(Windows)、图标(Icons)、菜单(Menu)、指示装置(Pointing Devices),图形用户界面
+ 4. 多媒体计算机
+ 5. 虚拟现实系统
+
+## 8 处理器模式
+
+1. 计算机通过设置处理器模式实现特权指令管理
+2. 计算机一般设置0、1、2、3四种运行模式,建议分别对应:
+ 1. 0:操作系统内核
+ 2. 1:系统调用
+ 3. 2:共享库程序
+ 4. 3:用户程序等保护级别
+3. 0模式可以执行全部指令;3模式只能执行非特权指令;其他每种运行模式可以规定执行的指令子集
+4. 一般来说,现代操作系统只使用0和3两种模式,对应于内核模式和用户模式
+
+### 处理器模式切换
+
+1. 简称模式切换,包括“用户模式→内核模式”和“内核模式→用户模式”的转换
+2. 中断、异常或系统异常等事件导致用户程序向OS内核切换,触发:用户模式→内核模式
+ 1. 程序请求操作系统服务
+ 2. 程序运行时发生异常
+ 3. 程序运行时发生并响应中断
+3. OS内核处理完成后,调用中断返回指令(如Inter的iret)触发:内核模式→用户模式
diff --git a/操作系统/image/2021-03-29-18-49-41.png b/操作系统/image/2021-03-29-18-49-41.png
new file mode 100644
index 00000000..b8e03fd8
Binary files /dev/null and b/操作系统/image/2021-03-29-18-49-41.png differ
diff --git a/操作系统/image/2021-03-29-18-57-45.png b/操作系统/image/2021-03-29-18-57-45.png
new file mode 100644
index 00000000..3be82b2f
Binary files /dev/null and b/操作系统/image/2021-03-29-18-57-45.png differ
diff --git a/操作系统/image/2021-03-29-19-12-03.png b/操作系统/image/2021-03-29-19-12-03.png
new file mode 100644
index 00000000..83b59018
Binary files /dev/null and b/操作系统/image/2021-03-29-19-12-03.png differ
diff --git a/操作系统/image/2021-03-29-19-19-37.png b/操作系统/image/2021-03-29-19-19-37.png
new file mode 100644
index 00000000..0c34bca1
Binary files /dev/null and b/操作系统/image/2021-03-29-19-19-37.png differ
diff --git a/操作系统/image/2021-03-29-19-41-25.png b/操作系统/image/2021-03-29-19-41-25.png
new file mode 100644
index 00000000..ade659f6
Binary files /dev/null and b/操作系统/image/2021-03-29-19-41-25.png differ
diff --git a/操作系统/image/2021-03-29-19-42-48.png b/操作系统/image/2021-03-29-19-42-48.png
new file mode 100644
index 00000000..f03413a1
Binary files /dev/null and b/操作系统/image/2021-03-29-19-42-48.png differ
diff --git a/操作系统/image/2021-03-29-19-48-17.png b/操作系统/image/2021-03-29-19-48-17.png
new file mode 100644
index 00000000..66a77fd8
Binary files /dev/null and b/操作系统/image/2021-03-29-19-48-17.png differ
diff --git a/操作系统/image/2021-03-29-19-49-37.png b/操作系统/image/2021-03-29-19-49-37.png
new file mode 100644
index 00000000..2b2ee6fc
Binary files /dev/null and b/操作系统/image/2021-03-29-19-49-37.png differ
diff --git a/操作系统/image/2021-03-29-19-53-09.png b/操作系统/image/2021-03-29-19-53-09.png
new file mode 100644
index 00000000..918ee56b
Binary files /dev/null and b/操作系统/image/2021-03-29-19-53-09.png differ
diff --git a/操作系统/image/2021-03-29-19-54-14.png b/操作系统/image/2021-03-29-19-54-14.png
new file mode 100644
index 00000000..a1439599
Binary files /dev/null and b/操作系统/image/2021-03-29-19-54-14.png differ
diff --git a/操作系统/image/2021-03-29-20-01-44.png b/操作系统/image/2021-03-29-20-01-44.png
new file mode 100644
index 00000000..777e3a2d
Binary files /dev/null and b/操作系统/image/2021-03-29-20-01-44.png differ
diff --git a/操作系统/image/2021-03-29-20-01-54.png b/操作系统/image/2021-03-29-20-01-54.png
new file mode 100644
index 00000000..3eeac09a
Binary files /dev/null and b/操作系统/image/2021-03-29-20-01-54.png differ
diff --git a/操作系统/image/2021-03-29-20-02-02.png b/操作系统/image/2021-03-29-20-02-02.png
new file mode 100644
index 00000000..0322b5d6
Binary files /dev/null and b/操作系统/image/2021-03-29-20-02-02.png differ
diff --git a/操作系统/image/2021-03-29-20-02-49.png b/操作系统/image/2021-03-29-20-02-49.png
new file mode 100644
index 00000000..8cd83aac
Binary files /dev/null and b/操作系统/image/2021-03-29-20-02-49.png differ
diff --git a/操作系统/image/2021-03-29-20-03-28.png b/操作系统/image/2021-03-29-20-03-28.png
new file mode 100644
index 00000000..84ee1613
Binary files /dev/null and b/操作系统/image/2021-03-29-20-03-28.png differ
diff --git a/操作系统/image/2021-03-29-20-15-32.png b/操作系统/image/2021-03-29-20-15-32.png
new file mode 100644
index 00000000..13ab94be
Binary files /dev/null and b/操作系统/image/2021-03-29-20-15-32.png differ
diff --git a/操作系统/image/2021-03-29-20-16-28.png b/操作系统/image/2021-03-29-20-16-28.png
new file mode 100644
index 00000000..8e2e3eb4
Binary files /dev/null and b/操作系统/image/2021-03-29-20-16-28.png differ
diff --git a/操作系统/image/2021-03-29-20-39-11.png b/操作系统/image/2021-03-29-20-39-11.png
new file mode 100644
index 00000000..0158187f
Binary files /dev/null and b/操作系统/image/2021-03-29-20-39-11.png differ
diff --git a/操作系统/image/2021-03-29-20-39-28.png b/操作系统/image/2021-03-29-20-39-28.png
new file mode 100644
index 00000000..a08f2f68
Binary files /dev/null and b/操作系统/image/2021-03-29-20-39-28.png differ
diff --git a/操作系统/image/2021-03-29-20-41-37.png b/操作系统/image/2021-03-29-20-41-37.png
new file mode 100644
index 00000000..aa797233
Binary files /dev/null and b/操作系统/image/2021-03-29-20-41-37.png differ
diff --git a/操作系统/image/2021-03-29-22-38-00.png b/操作系统/image/2021-03-29-22-38-00.png
new file mode 100644
index 00000000..2653f36e
Binary files /dev/null and b/操作系统/image/2021-03-29-22-38-00.png differ
diff --git a/操作系统/image/2021-03-29-22-38-38.png b/操作系统/image/2021-03-29-22-38-38.png
new file mode 100644
index 00000000..66fd599d
Binary files /dev/null and b/操作系统/image/2021-03-29-22-38-38.png differ
diff --git a/操作系统/image/2021-03-29-22-50-04.png b/操作系统/image/2021-03-29-22-50-04.png
new file mode 100644
index 00000000..27fc11f5
Binary files /dev/null and b/操作系统/image/2021-03-29-22-50-04.png differ
diff --git a/操作系统/image/2021-03-29-22-52-14.png b/操作系统/image/2021-03-29-22-52-14.png
new file mode 100644
index 00000000..27fc11f5
Binary files /dev/null and b/操作系统/image/2021-03-29-22-52-14.png differ
diff --git a/操作系统/image/2021-03-29-22-53-11.png b/操作系统/image/2021-03-29-22-53-11.png
new file mode 100644
index 00000000..9b2c90fb
Binary files /dev/null and b/操作系统/image/2021-03-29-22-53-11.png differ
diff --git a/操作系统/image/2021-03-29-22-54-26.png b/操作系统/image/2021-03-29-22-54-26.png
new file mode 100644
index 00000000..d2fe7257
Binary files /dev/null and b/操作系统/image/2021-03-29-22-54-26.png differ
diff --git a/操作系统/image/2021-03-29-22-56-33.png b/操作系统/image/2021-03-29-22-56-33.png
new file mode 100644
index 00000000..90e87717
Binary files /dev/null and b/操作系统/image/2021-03-29-22-56-33.png differ
diff --git a/操作系统/image/2021-03-29-22-57-07.png b/操作系统/image/2021-03-29-22-57-07.png
new file mode 100644
index 00000000..574a33f9
Binary files /dev/null and b/操作系统/image/2021-03-29-22-57-07.png differ
diff --git a/操作系统/计算机操作系统 - 内存管理.md b/操作系统/计算机操作系统 - 内存管理.md
new file mode 100644
index 00000000..9b0b78be
--- /dev/null
+++ b/操作系统/计算机操作系统 - 内存管理.md
@@ -0,0 +1,141 @@
+# 计算机操作系统 - 内存管理
+
+* [计算机操作系统 - 内存管理](#计算机操作系统---内存管理)
+ * [虚拟内存](#虚拟内存)
+ * [分页系统地址映射](#分页系统地址映射)
+ * [页面置换算法](#页面置换算法)
+ * [1. 最佳](#1-最佳)
+ * [2. 最近最久未使用](#2-最近最久未使用)
+ * [3. 最近未使用](#3-最近未使用)
+ * [4. 先进先出](#4-先进先出)
+ * [5. 第二次机会算法](#5-第二次机会算法)
+ * [6. 时钟](#6-时钟)
+ * [分段](#分段)
+ * [段页式](#段页式)
+ * [分页与分段的比较](#分页与分段的比较)
+
+
+
+## 虚拟内存
+
+虚拟内存的目的是为了让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。
+
+为了更好的管理内存,操作系统将内存抽象成地址空间。每个程序拥有自己的地址空间,这个地址空间被分割成多个块,每一块称为一页。这些页被映射到物理内存,但不需要映射到连续的物理内存,也不需要所有页都必须在物理内存中。当程序引用到不在物理内存中的页时,由硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。
+
+从上面的描述中可以看出,虚拟内存允许程序不用将地址空间中的每一页都映射到物理内存,也就是说一个程序不需要全部调入内存就可以运行,这使得有限的内存运行大程序成为可能。例如有一台计算机可以产生 16 位地址,那么一个程序的地址空间范围是 0\~64K。该计算机只有 32KB 的物理内存,虚拟内存技术允许该计算机运行一个 64K 大小的程序。
+
+
+
+## 分页系统地址映射
+
+内存管理单元(MMU)管理着地址空间和物理内存的转换,其中的页表(Page table)存储着页(程序地址空间)和页框(物理内存空间)的映射表。
+
+一个虚拟地址分成两个部分,一部分存储页面号,一部分存储偏移量。
+
+下图的页表存放着 16 个页,这 16 个页需要用 4 个比特位来进行索引定位。例如对于虚拟地址(0010 000000000100),前 4 位是存储页面号 2,读取表项内容为(110 1),页表项最后一位表示是否存在于内存中,1 表示存在。后 12 位存储偏移量。这个页对应的页框的地址为 (110 000000000100)。
+
+
+
+## 页面置换算法
+
+在程序运行过程中,如果要访问的页面不在内存中,就发生缺页中断从而将该页调入内存中。此时如果内存已无空闲空间,系统必须从内存中调出一个页面到磁盘对换区中来腾出空间。
+
+页面置换算法和缓存淘汰策略类似,可以将内存看成磁盘的缓存。在缓存系统中,缓存的大小有限,当有新的缓存到达时,需要淘汰一部分已经存在的缓存,这样才有空间存放新的缓存数据。
+
+页面置换算法的主要目标是使页面置换频率最低(也可以说缺页率最低)。
+
+### 1. 最佳
+
+> OPT, Optimal replacement algorithm
+
+所选择的被换出的页面将是最长时间内不再被访问,通常可以保证获得最低的缺页率。
+
+是一种理论上的算法,因为无法知道一个页面多长时间不再被访问。
+
+举例:一个系统为某进程分配了三个物理块,并有如下页面引用序列:
+
+```html
+7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1
+```
+
+开始运行时,先将 7, 0, 1 三个页面装入内存。当进程要访问页面 2 时,产生缺页中断,会将页面 7 换出,因为页面 7 再次被访问的时间最长。
+
+### 2. 最近最久未使用
+
+> LRU, Least Recently Used
+
+虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU 将最近最久未使用的页面换出。
+
+为了实现 LRU,需要在内存中维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。
+
+因为每次访问都需要更新链表,因此这种方式实现的 LRU 代价很高。
+
+```html
+4,7,0,7,1,0,1,2,1,2,6
+```
+
+
+### 3. 最近未使用
+
+> NRU, Not Recently Used
+
+每个页面都有两个状态位:R 与 M,当页面被访问时设置页面的 R=1,当页面被修改时设置 M=1。其中 R 位会定时被清零。可以将页面分成以下四类:
+
+- R=0,M=0
+- R=0,M=1
+- R=1,M=0
+- R=1,M=1
+
+当发生缺页中断时,NRU 算法随机地从类编号最小的非空类中挑选一个页面将它换出。
+
+NRU 优先换出已经被修改的脏页面(R=0,M=1),而不是被频繁使用的干净页面(R=1,M=0)。
+
+### 4. 先进先出
+
+> FIFO, First In First Out
+
+选择换出的页面是最先进入的页面。
+
+该算法会将那些经常被访问的页面换出,导致缺页率升高。
+
+### 5. 第二次机会算法
+
+FIFO 算法可能会把经常使用的页面置换出去,为了避免这一问题,对该算法做一个简单的修改:
+
+当页面被访问 (读或写) 时设置该页面的 R 位为 1。需要替换的时候,检查最老页面的 R 位。如果 R 位是 0,那么这个页面既老又没有被使用,可以立刻置换掉;如果是 1,就将 R 位清 0,并把该页面放到链表的尾端,修改它的装入时间使它就像刚装入的一样,然后继续从链表的头部开始搜索。
+
+
+
+### 6. 时钟
+
+> Clock
+
+第二次机会算法需要在链表中移动页面,降低了效率。时钟算法使用环形链表将页面连接起来,再使用一个指针指向最老的页面。
+
+
+
+## 分段
+
+虚拟内存采用的是分页技术,也就是将地址空间划分成固定大小的页,每一页再与内存进行映射。
+
+下图为一个编译器在编译过程中建立的多个表,有 4 个表是动态增长的,如果使用分页系统的一维地址空间,动态增长的特点会导致覆盖问题的出现。
+
+
+
+分段的做法是把每个表分成段,一个段构成一个独立的地址空间。每个段的长度可以不同,并且可以动态增长。
+
+
+
+## 段页式
+
+程序的地址空间划分成多个拥有独立地址空间的段,每个段上的地址空间划分成大小相同的页。这样既拥有分段系统的共享和保护,又拥有分页系统的虚拟内存功能。
+
+## 分页与分段的比较
+
+- 对程序员的透明性:分页透明,但是分段需要程序员显式划分每个段。
+
+- 地址空间的维度:分页是一维地址空间,分段是二维的。
+
+- 大小是否可以改变:页的大小不可变,段的大小可以动态改变。
+
+- 出现的原因:分页主要用于实现虚拟内存,从而获得更大的地址空间;分段主要是为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护。
diff --git a/操作系统/计算机操作系统 - 死锁.md b/操作系统/计算机操作系统 - 死锁.md
new file mode 100644
index 00000000..d58e7f43
--- /dev/null
+++ b/操作系统/计算机操作系统 - 死锁.md
@@ -0,0 +1,144 @@
+# 计算机操作系统 - 死锁
+
+* [计算机操作系统 - 死锁](#计算机操作系统---死锁)
+ * [必要条件](#必要条件)
+ * [处理方法](#处理方法)
+ * [鸵鸟策略](#鸵鸟策略)
+ * [死锁检测与死锁恢复](#死锁检测与死锁恢复)
+ * [1. 每种类型一个资源的死锁检测](#1-每种类型一个资源的死锁检测)
+ * [2. 每种类型多个资源的死锁检测](#2-每种类型多个资源的死锁检测)
+ * [3. 死锁恢复](#3-死锁恢复)
+ * [死锁预防](#死锁预防)
+ * [1. 破坏互斥条件](#1-破坏互斥条件)
+ * [2. 破坏占有和等待条件](#2-破坏占有和等待条件)
+ * [3. 破坏不可抢占条件](#3-破坏不可抢占条件)
+ * [4. 破坏环路等待](#4-破坏环路等待)
+ * [死锁避免](#死锁避免)
+ * [1. 安全状态](#1-安全状态)
+ * [2. 单个资源的银行家算法](#2-单个资源的银行家算法)
+ * [3. 多个资源的银行家算法](#3-多个资源的银行家算法)
+
+
+
+## 必要条件
+
+
+
+- 互斥:每个资源要么已经分配给了一个进程,要么就是可用的。
+- 占有和等待:已经得到了某个资源的进程可以再请求新的资源。
+- 不可抢占:已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。
+- 环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源。
+
+## 处理方法
+
+主要有以下四种方法:
+
+- 鸵鸟策略
+- 死锁检测与死锁恢复
+- 死锁预防
+- 死锁避免
+
+## 鸵鸟策略
+
+把头埋在沙子里,假装根本没发生问题。
+
+因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。
+
+当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。
+
+大多数操作系统,包括 Unix,Linux 和 Windows,处理死锁问题的办法仅仅是忽略它。
+
+## 死锁检测与死锁恢复
+
+不试图阻止死锁,而是当检测到死锁发生时,采取措施进行恢复。
+
+### 1. 每种类型一个资源的死锁检测
+
+
+
+上图为资源分配图,其中方框表示资源,圆圈表示进程。资源指向进程表示该资源已经分配给该进程,进程指向资源表示进程请求获取该资源。
+
+图 a 可以抽取出环,如图 b,它满足了环路等待条件,因此会发生死锁。
+
+每种类型一个资源的死锁检测算法是通过检测有向图是否存在环来实现,从一个节点出发进行深度优先搜索,对访问过的节点进行标记,如果访问了已经标记的节点,就表示有向图存在环,也就是检测到死锁的发生。
+
+### 2. 每种类型多个资源的死锁检测
+
+
+
+上图中,有三个进程四个资源,每个数据代表的含义如下:
+
+- E 向量:资源总量
+- A 向量:资源剩余量
+- C 矩阵:每个进程所拥有的资源数量,每一行都代表一个进程拥有资源的数量
+- R 矩阵:每个进程请求的资源数量
+
+进程 P1 和 P2 所请求的资源都得不到满足,只有进程 P3 可以,让 P3 执行,之后释放 P3 拥有的资源,此时 A = (2 2 2 0)。P2 可以执行,执行后释放 P2 拥有的资源,A = (4 2 2 1) 。P1 也可以执行。所有进程都可以顺利执行,没有死锁。
+
+算法总结如下:
+
+每个进程最开始时都不被标记,执行过程有可能被标记。当算法结束时,任何没有被标记的进程都是死锁进程。
+
+1. 寻找一个没有标记的进程 Pi,它所请求的资源小于等于 A。
+2. 如果找到了这样一个进程,那么将 C 矩阵的第 i 行向量加到 A 中,标记该进程,并转回 1。
+3. 如果没有这样一个进程,算法终止。
+
+### 3. 死锁恢复
+
+- 利用抢占恢复
+- 利用回滚恢复
+- 通过杀死进程恢复
+
+## 死锁预防
+
+在程序运行之前预防发生死锁。
+
+### 1. 破坏互斥条件
+
+例如假脱机打印机技术允许若干个进程同时输出,唯一真正请求物理打印机的进程是打印机守护进程。
+
+### 2. 破坏占有和等待条件
+
+一种实现方式是规定所有进程在开始执行前请求所需要的全部资源。
+
+### 3. 破坏不可抢占条件
+
+### 4. 破坏环路等待
+
+给资源统一编号,进程只能按编号顺序来请求资源。
+
+## 死锁避免
+
+在程序运行时避免发生死锁。
+
+### 1. 安全状态
+
+
+
+图 a 的第二列 Has 表示已拥有的资源数,第三列 Max 表示总共需要的资源数,Free 表示还有可以使用的资源数。从图 a 开始出发,先让 B 拥有所需的所有资源(图 b),运行结束后释放 B,此时 Free 变为 5(图 c);接着以同样的方式运行 C 和 A,使得所有进程都能成功运行,因此可以称图 a 所示的状态时安全的。
+
+定义:如果没有死锁发生,并且即使所有进程突然请求对资源的最大需求,也仍然存在某种调度次序能够使得每一个进程运行完毕,则称该状态是安全的。
+
+安全状态的检测与死锁的检测类似,因为安全状态必须要求不能发生死锁。下面的银行家算法与死锁检测算法非常类似,可以结合着做参考对比。
+
+### 2. 单个资源的银行家算法
+
+一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,算法要做的是判断对请求的满足是否会进入不安全状态,如果是,就拒绝请求;否则予以分配。
+
+
+
+上图 c 为不安全状态,因此算法会拒绝之前的请求,从而避免进入图 c 中的状态。
+
+### 3. 多个资源的银行家算法
+
+
+
+上图中有五个进程,四个资源。左边的图表示已经分配的资源,右边的图表示还需要分配的资源。最右边的 E、P 以及 A 分别表示:总资源、已分配资源以及可用资源,注意这三个为向量,而不是具体数值,例如 A=(1020),表示 4 个资源分别还剩下 1/0/2/0。
+
+检查一个状态是否安全的算法如下:
+
+- 查找右边的矩阵是否存在一行小于等于向量 A。如果不存在这样的行,那么系统将会发生死锁,状态是不安全的。
+- 假若找到这样一行,将该进程标记为终止,并将其已分配资源加到 A 中。
+- 重复以上两步,直到所有进程都标记为终止,则状态时安全的。
+
+如果一个状态不是安全的,需要拒绝进入这个状态。
diff --git a/操作系统/计算机操作系统 - 目录.md b/操作系统/计算机操作系统 - 目录.md
new file mode 100644
index 00000000..f3054311
--- /dev/null
+++ b/操作系统/计算机操作系统 - 目录.md
@@ -0,0 +1,20 @@
+# 计算机操作系统
+
+- [概述](计算机操作系统%20-%20概述.md)
+- [进程管理](计算机操作系统%20-%20进程管理.md)
+- [死锁](计算机操作系统%20-%20死锁.md)
+- [内存管理](计算机操作系统%20-%20内存管理.md)
+- [设备管理](计算机操作系统%20-%20设备管理.md)
+- [链接](计算机操作系统%20-%20链接.md)
+
+## 参考资料
+
+- Tanenbaum A S, Bos H. Modern operating systems[M]. Prentice Hall Press, 2014.
+- 汤子瀛, 哲凤屏, 汤小丹. 计算机操作系统[M]. 西安电子科技大学出版社, 2001.
+- Bryant, R. E., & O’Hallaron, D. R. (2004). 深入理解计算机系统.
+- 史蒂文斯. UNIX 环境高级编程 [M]. 人民邮电出版社, 2014.
+- [Operating System Notes](https://applied-programming.github.io/Operating-Systems-Notes/)
+- [Operating-System Structures](https://www.cs.uic.edu/\~jbell/CourseNotes/OperatingSystems/2_Structures.html)
+- [Processes](http://cse.csusb.edu/tongyu/courses/cs460/notes/process.php)
+- [Inter Process Communication Presentation[1]](https://www.slideshare.net/rkolahalam/inter-process-communication-presentation1)
+- [Decoding UCS Invicta – Part 1](https://blogs.cisco.com/datacenter/decoding-ucs-invicta-part-1)
diff --git a/操作系统/计算机操作系统 - 设备管理.md b/操作系统/计算机操作系统 - 设备管理.md
new file mode 100644
index 00000000..95c7924d
--- /dev/null
+++ b/操作系统/计算机操作系统 - 设备管理.md
@@ -0,0 +1,61 @@
+# 计算机操作系统 - 设备管理
+
+* [计算机操作系统 - 设备管理](#计算机操作系统---设备管理)
+ * [磁盘结构](#磁盘结构)
+ * [磁盘调度算法](#磁盘调度算法)
+ * [1. 先来先服务](#1-先来先服务)
+ * [2. 最短寻道时间优先](#2-最短寻道时间优先)
+ * [3. 电梯算法](#3-电梯算法)
+
+
+
+## 磁盘结构
+
+- 盘面(Platter):一个磁盘有多个盘面;
+- 磁道(Track):盘面上的圆形带状区域,一个盘面可以有多个磁道;
+- 扇区(Track Sector):磁道上的一个弧段,一个磁道可以有多个扇区,它是最小的物理储存单位,目前主要有 512 bytes 与 4 K 两种大小;
+- 磁头(Head):与盘面非常接近,能够将盘面上的磁场转换为电信号(读),或者将电信号转换为盘面的磁场(写);
+- 制动手臂(Actuator arm):用于在磁道之间移动磁头;
+- 主轴(Spindle):使整个盘面转动。
+
+
+
+## 磁盘调度算法
+
+读写一个磁盘块的时间的影响因素有:
+
+- 旋转时间(主轴转动盘面,使得磁头移动到适当的扇区上)
+- 寻道时间(制动手臂移动,使得磁头移动到适当的磁道上)
+- 实际的数据传输时间
+
+其中,寻道时间最长,因此磁盘调度的主要目标是使磁盘的平均寻道时间最短。
+
+### 1. 先来先服务
+
+> FCFS, First Come First Served
+
+按照磁盘请求的顺序进行调度。
+
+优点是公平和简单。缺点也很明显,因为未对寻道做任何优化,使平均寻道时间可能较长。
+
+### 2. 最短寻道时间优先
+
+> SSTF, Shortest Seek Time First
+
+优先调度与当前磁头所在磁道距离最近的磁道。
+
+虽然平均寻道时间比较低,但是不够公平。如果新到达的磁道请求总是比一个在等待的磁道请求近,那么在等待的磁道请求会一直等待下去,也就是出现饥饿现象。具体来说,两端的磁道请求更容易出现饥饿现象。
+
+
+
+### 3. 电梯算法
+
+> SCAN
+
+电梯总是保持一个方向运行,直到该方向没有请求为止,然后改变运行方向。
+
+电梯算法(扫描算法)和电梯的运行过程类似,总是按一个方向来进行磁盘调度,直到该方向上没有未完成的磁盘请求,然后改变方向。
+
+因为考虑了移动方向,因此所有的磁盘请求都会被满足,解决了 SSTF 的饥饿问题。
+
+
diff --git a/操作系统/计算机操作系统 - 进程管理.md b/操作系统/计算机操作系统 - 进程管理.md
new file mode 100644
index 00000000..e69de29b
diff --git a/操作系统/计算机操作系统 - 链接.md b/操作系统/计算机操作系统 - 链接.md
new file mode 100644
index 00000000..a06caa1b
--- /dev/null
+++ b/操作系统/计算机操作系统 - 链接.md
@@ -0,0 +1,68 @@
+# 计算机操作系统 - 链接
+
+* [计算机操作系统 - 链接](#计算机操作系统---链接)
+ * [编译系统](#编译系统)
+ * [静态链接](#静态链接)
+ * [目标文件](#目标文件)
+ * [动态链接](#动态链接)
+
+
+
+## 编译系统
+
+
+以下是一个 hello.c 程序:
+
+```c
+#include
+
+int main()
+{
+ printf("hello, world\n");
+ return 0;
+}
+```
+
+在 Unix 系统上,由编译器把源文件转换为目标文件。
+
+```bash
+gcc -o hello hello.c
+```
+
+这个过程大致如下:
+
+
+
+- 预处理阶段:处理以 # 开头的预处理命令;
+- 编译阶段:翻译成汇编文件;
+- 汇编阶段:将汇编文件翻译成可重定位目标文件;
+- 链接阶段:将可重定位目标文件和 printf.o 等单独预编译好的目标文件进行合并,得到最终的可执行目标文件。
+
+## 静态链接
+
+静态链接器以一组可重定位目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务:
+
+- 符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。
+- 重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。
+
+
+
+## 目标文件
+
+- 可执行目标文件:可以直接在内存中执行;
+- 可重定位目标文件:可与其它可重定位目标文件在链接阶段合并,创建一个可执行目标文件;
+- 共享目标文件:这是一种特殊的可重定位目标文件,可以在运行时被动态加载进内存并链接;
+
+## 动态链接
+
+静态库有以下两个问题:
+
+- 当静态库更新时那么整个程序都要重新进行链接;
+- 对于 printf 这种标准函数库,如果每个程序都要有代码,这会极大浪费资源。
+
+共享库是为了解决静态库的这两个问题而设计的,在 Linux 系统中通常用 .so 后缀来表示,Windows 系统上它们被称为 DLL。它具有以下特点:
+
+- 在给定的文件系统中一个库只有一个文件,所有引用该库的可执行目标文件都共享这个文件,它不会被复制到引用它的可执行文件中;
+- 在内存中,一个共享库的 .text 节(已编译程序的机器代码)的一个副本可以被不同的正在运行的进程共享。
+
+
diff --git a/操作系统/计算机操作系统.md b/操作系统/计算机操作系统.md
new file mode 100644
index 00000000..c7dcdb10
--- /dev/null
+++ b/操作系统/计算机操作系统.md
@@ -0,0 +1 @@
+[计算机操作系统](https://github.com/CyC2018/CS-Notes/blob/master/notes/%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%20-%20%E7%9B%AE%E5%BD%95.md)
diff --git a/操作系统/计算机操作系统.xmind b/操作系统/计算机操作系统.xmind
new file mode 100644
index 00000000..41fae56b
Binary files /dev/null and b/操作系统/计算机操作系统.xmind differ
diff --git a/操作系统/附录1 课后习题答案.md b/操作系统/附录1 课后习题答案.md
new file mode 100644
index 00000000..a411cef5
--- /dev/null
+++ b/操作系统/附录1 课后习题答案.md
@@ -0,0 +1,2105 @@
+# 计算机操作系统(第3版)课后习题答案
+
+> 参考链接
+> * [https://blog.csdn.net/skymyxvincent/article/details/52851675](https://blog.csdn.net/skymyxvincent/article/details/52851675)
+
+## 第一章
+
+**1.设计现代OS的主要目标是什么?**
+
+答:(1)有效性 (2)方便性 (3)可扩充性 (4)开放性
+
+**2.OS的作用可表现在哪几个方面?**
+
+1. OS作为用户与计算机硬件系统之间的接口
+
+2. OS作为计算机系统资源的管理者
+
+3. OS实现了对计算机资源的抽象
+
+**3.为什么说OS实现了对计算机资源的抽象?**
+
+答:OS首先在裸机上覆盖一层I/O设备管理软件,实现了对计算机硬件操作的第一层次抽象;在第一层软件上再覆盖文件管理软件,实现了对硬件资源操作的第二层次抽象。OS 通过在计算机硬件上安装多层系统软件,增强了系统功能,隐藏了对硬件操作的细节,由它们共同实现了对计算机资源的抽象。
+
+**4.试说明推动多道批处理系统形成和发展的主要动力是什么?**
+
+答:主要动力来源于四个方面的社会需求与技术发展:
+
+1. 不断提高计算机资源的利用率;
+
+2. 方便用户;
+
+3. 器件的不断更新换代;
+
+4. 计算机体系结构的不断发展。
+
+**5.何谓脱机I/O和联机I/O?**
+
+答:脱机I/O 是指事先将装有用户程序和数据的纸带或卡片装入纸带输入机或卡片机,在外围机的控制下,把纸带或卡片上的数据或程序输入到磁带上。该方式下的输入输出由外围机控制完成,是在脱离主机的情况下进行的。而联机I/O方式是指程序和数据的输入输出都是在主机的直接控制下进行的。
+
+**6.试说明推动分时系统形成和发展的主要动力是什么?**
+
+答:推动分时系统形成和发展的主要动力是更好地满足用户的需要。主要表现在:CPU 的分时使用缩短了作业的平均周转时间;人机交互能力使用户能直接控制自己的作业;主机的共享使多用户能同时使用同一台计算机,独立地处理自己的作业。
+
+**7.实现分时系统的关键问题是什么?应如何解决?**
+
+答:关键问题是当用户在自己的终端上键入命令时,系统应能及时接收并及时处理该命令,在用户能接受的时延内将结果返回给用户。
+
+解决方法:针对及时接收问题,可以在系统中设置多路卡,使主机能同时接收用户从各个终端上输入的数据;为每个终端配置缓冲区,暂存用户键入的命令或数据。针对及时处理问题,应使所有的用户作业都直接进入内存,并且为每个作业分配一个时间片,允许作业只在自己的时间片内运行,这样在不长的时间内,能使每个作业都运行一次。
+
+**8.为什么要引入实时OS?**
+
+答:实时操作系统是指系统能及时响应外部事件的请求,在规定的时间内完成对该事件的处理,并控制所有实时任务协调一致地运行。引入实时OS 是为了满足应用的需求,更好地满足实时控制领域和实时信息处理领域的需要。
+
+**9.什么是硬实时任务和软实时任务?试举例说明。**
+
+答:硬实时任务是指系统必须满足任务对截止时间的要求,否则可能出现难以预测的结果。举例来说,运载火箭的控制等。软实时任务是指它的截止时间并不严格,偶尔错过了任务的截止时间,对系统产生的影响不大。举例:网页内容的更新、火车售票系统。
+
+**10.在8位微机和16位微机中,占据了统治地位的是什么操作系统?**
+
+答:单用户单任务操作系统,其中最具代表性的是CP/M和MS-DOS.
+
+**11.试列出Windows OS中五个主要版本,并说明它们分别较之前一个版本有何改进。**
+
+1. Microsoft Windows 1.0是微软公司在个人电脑上开发图形界面的首次尝试。
+
+2. Windows 95是混合的16位/32位系统,第一个支持32位。带来了更强大、更稳定、更实用的桌面图形用户界面,结束了桌面操作系统间的竞争。
+
+3. Windows 98是微软公司的混合16位/32位Windows操作系统,改良了硬件标准的支持,革新了内存管理,是多进程操作系统。
+
+4. Windows XP 是基于Windows 2000的产品,拥有新用户图形界面月神Luna。简化了用户安全特性,整合了防火墙。
+
+5. Windows Vista 包含了上百种新功能;特别是新版图形用户界面和Windows Aero 全新界面风格、加强的搜寻功能(Windows Indexing Service)、新媒体创作工具以及重新设计的网络、音频、输出(打印)和显示子系统。。
+
+**12.试从交互性、及时性以及可靠性方面,将分时系统与实时系统进行比较。**
+
+1. 及时性:实时信息处理系统对实时性的要求与分时系统类似,都是以人所能接受的等待时间来确定;而实时控制系统的及时性,是以控制对象所要求的开始截止时间或完成截止时间来确定的,一般为秒级到毫秒级,甚至有的要低于100微秒。
+
+2. 交互性:实时信息处理系统具有交互性,但人与系统的交互仅限于访问系统中某些特定的专用服务程序。不像分时系统那样能向终端用户提供数据和资源共享等服务。
+
+3. 可靠性:分时系统也要求系统可靠,但相比之下,实时系统则要求系统具有高度的可靠性。因为任何差错都可能带来巨大的经济损失,甚至是灾难性后果,所以在实时系统中,往往都采取了多级容错措施保障系统的安全性及数据的安全性。
+
+**13.OS有哪几大特征?其最基本的特征是什么?**
+
+答:并发性、共享性、虚拟性和异步性四个基本特征;最基本的特征是并发性。
+
+**14.处理机管理有哪些主要功能?它们的主要任务是什么?**
+
+答:处理机管理的主要功能是:进程管理、进程同步、进程通信和处理机调度;
+
+进程管理:为作业创建进程,撤销已结束进程,控制进程在运行过程中的状态转换。
+
+进程同步:为多个进程(含线程)的运行进行协调。
+
+通信:用来实现在相互合作的进程之间的信息交换。
+
+处理机调度:
+
+1. 作业调度:从后备队里按照一定的算法,选出若干个作业,为他们分配运行所需的资源(首选是分配内存)。
+
+2. 进程调度:从进程的就绪队列中,按照一定算法选出一个进程,把处理机分配给它,并设置运行现场,使进程投入执行。
+
+**15.内存管理有哪些主要功能?他们的主要任务是什么?**
+
+答:内存管理的主要功能有:内存分配、内存保护、地址映射和内存扩充。
+
+内存分配:为每道程序分配内存。
+
+内存保护:确保每道用户程序都只在自己的内存空间运行,彼此互不干扰。
+
+地址映射:将地址空间的逻辑地址转换为内存空间与对应的物理地址。
+
+内存扩充:用于实现请求调用功能,置换功能等。
+
+**16.设备管理有哪些主要功能?其主要任务是什么?**
+
+答:主要功能有: 缓冲管理、设备分配和设备处理以及虚拟设备等。
+
+主要任务: 完成用户提出的I/O请求,为用户分配I/O设备;提高CPU 和I/O设备的利用率;提高I/O速度;以及方便用户使用I/O设备.
+
+**17.文件管理有哪些主要功能?其主要任务是什么?**
+
+答:文件管理主要功能:文件存储空间的管理、目录管理、文件的读/写管理和保护。
+
+文件管理的主要任务:管理用户文件和系统文件,方便用户使用,保证文件安全性。
+
+**18.是什么原因使操作系统具有异步性特征?**
+
+答:操作系统的异步性体现在三个方面:一是进程的异步性,进程以人们不可预知的速度向
+
+前推进,二是程序的不可再现性,即程序执行的结果有时是不确定的,三是程序执行时间的
+
+不可预知性,即每个程序何时执行,执行顺序以及完成时间是不确定的。
+
+**19.模块接口法存在哪些问题?可通过什么样的途径来解决?**
+
+答:(1)模块接口法存在的问题:①在OS设计时,各模块间的接口规定很难满足在模块完成后对接口的实际需求。②在OS 设计阶段,设计者必须做出一系列的决定,每一个决定必须建立在上一个决定的基础上。但模块化结构设计的各模块设计齐头并进,无法寻找可靠的顺序,造成各种决定的无序性,使程序设计人员很难做到设计中的每一步决定都建立在可靠的基础上,因此模块接口法被称为“无序模块法”。
+
+(2)解决途径:将模块接口法的决定顺序无序变有序,引入有序分层法。
+
+**20.在微内核OS中,为什么要采用客户/服务器模式?**
+
+C/S 模式具有独特的优点:
+
+1. 数据的分布处理和存储
+2. 便于集中管理
+3. 灵活性和可扩充性
+4. 易于改编应用软件
+
+**21.试描述什么是微内核OS。**
+
+1. 足够小的内核
+2. 基于客户/服务器模式
+3. 应用机制与策略分离原理
+4. 采用面向对象技术。
+
+**22.在基于微内核结构的OS中,应用了哪些新技术?**
+
+答:在基于微内核结构的OS中,采用面向对象的程序设计技术。
+
+**23.何谓微内核技术?在微内核中通常提供了哪些功能?**
+
+答:把操作系统中更多的成分和功能放到更高的层次(即用户模式)中去运行,而留下一个尽量小的内核,用它来完成操作系统最基本的核心功能,称这种技术为微内核技术。在微内核中通常提供了进程(线程)管理、低级存储器管理、中断和陷入处理等功能。
+
+**24.微内核操作系统具有哪些优点?它为何能有这些优点?**
+
+1. 提高了系统的可扩展性
+2. 增强了系统的可靠性
+3. 可移植性
+4. 提供了对分布式系统的支持
+5. 融入了面向对象技术
+
+## 第二章
+
+**1. 什么是前趋图?为什么要引入前趋图?**
+
+答:前趋图(Precedence Graph)是一个有向无循环图,记为DAG(Directed Acyclic Graph),用于描述进程之间执行的前后关系。
+
+**2. 画出下面四条语句的前趋图:**
+
+**S1=a:=x+y; S2=b:=z+1; S3=c:=a – b;S4=w:=c+1;**
+
+答:其前趋图为:
+
+**3. 什么程序并发执行会产生间断性特征?**
+
+答:程序在并发执行时,由于它们共享系统资源,为完成同一项任务需要相互合作,致使这些并发执行的进程之间,形成了相互制约关系,从而使得进程在执行期间出现间断性。
+
+**4.程序并发执行时为什么会失去封闭性和可再现性?**
+
+答:程序并发执行时,多个程序共享系统中的各种资源,因而这些资源的状态由多个程序改变,致使程序运行失去了封闭性,也会导致其失去可再现性。
+
+**5.在操作系统中为什么要引入进程概念?它会产生什么样的影响?**
+
+答:为了使程序在多道程序环境下能并发执行,并对并发执行的程序加以控制和描述,在操作系统中引入了进程概念。影响:使程序的并发执行得以实行。
+
+**6.试从动态性,并发性和独立性上比较进程和程序?**
+
+1. 动态性是进程最基本的特性,表现为由创建而产生,由调度而执行,因得不到资源而暂停执行,由撤销而消亡。进程有一定的生命期,而程序只是一组有序的指令集合,是静态实体。
+2. 并发性是进程的重要特征,同时也是OS的重要特征。引入进程的目的正是为了使其程序能和其它进程的程序并发执行,而程序是不能并发执行的。
+3. 独立性是指进程实体是一个能独立运行的基本单位,也是系统中独立获得资源和独立调度的基本单位。对于未建立任何进程的程序,不能作为独立单位参加运行。
+
+**7.试说明PCB 的作用,为什么说PCB 是进程存在的惟一标志?**
+
+答:PCB是进程实体的一部分,是操作系统中最重要的记录型数据结构。作用是使一个在多道程序环境下不能独立运行的程序,成为一个能独立运行的基本单位,成为能与其它进程并发执行的进程。OS是根据PCB对并发执行的进程进行控制和管理的。
+
+**8.试说明进程在三个基本状态之间转换的典型原因。**
+
+1. 就绪状态→执行状态:进程分配到CPU资源
+2. 执行状态→就绪状态:时间片用完
+3. 执行状态→阻塞状态:I/O请求
+4. 阻塞状态→就绪状态:I/O完成
+
+**9.为什么要引入挂起状态?该状态有哪些性质?**
+
+答:引入挂起状态处于五种不同的需要:终端用户需要,父进程需要,操作系统需要,对换需要和负荷调节需要。处于挂起状态的进程不能接收处理机调度。
+
+**10.在进行进程切换时,所要保存的处理机状态信息有哪些?**
+
+答:进行进程切换时,所要保存的处理机状态信息有:
+
+1. 进程当前暂存信息
+2. 下一指令地址信息
+3. 进程状态信息
+4. 过程和系统调用参数及调用地址信息。
+
+**11.试说明引起进程创建的主要事件。**
+
+答:引起进程创建的主要事件有:用户登录、作业调度、提供服务、应用请求。
+
+**12.试说明引起进程被撤销的主要事件。**
+
+答:引起进程被撤销的主要事件有:正常结束、异常结束(越界错误、保护错、非法指令、特权指令错、运行超时、等待超时、算术运算错、I/O故障)、外界干预(操作员或操作系统干预、父进程请求、父进程终止)。
+
+**13.在创建一个进程时所要完成的主要工作是什么?**
+
+1. OS发现请求创建新进程事件后,调用进程创建原语 Creat();
+2. 申请空白PCB;
+3. 为新进程分配资源;
+4. 初始化进程控制块;
+5. 将新进程插入就绪队列.
+
+**14.在撤销一个进程时所要完成的主要工作是什么?**
+
+1. 根据被终止进程标识符,从PCB集中检索出进程PCB,读出该进程状态。
+2. 若被终止进程处于执行状态,立即终止该进程的执行,置调度标志真,指示该进程被终止后重新调度。
+3. 若该进程还有子进程,应将所有子孙进程终止,以防它们成为不可控进程。
+4. 将被终止进程拥有的全部资源,归还给父进程,或归还给系统。
+5. 将被终止进程PCB从所在队列或列表中移出,等待其它程序搜集信息。
+
+**15.试说明引起进程阻塞或被唤醒的主要事件是什么?**
+
+答:a. 请求系统服务;b. 启动某种操作;c. 新数据尚未到达;d. 无新工作可做.
+
+**16.进程在运行时存在哪两种形式的制约?并举例说明之。**
+
+1. 间接相互制约关系。举例:有两进程A 和B,如果A 提出打印请求,系统已把唯一的一台打印机分配给了进程B,则进程A 只能阻塞;一旦B 释放打印机,A 才由阻塞改为就绪。
+2. 直接相互制约关系。举例:有输入进程A 通过单缓冲向进程B 提供数据。当缓冲空时,计算进程因不能获得所需数据而阻塞,当进程A 把数据输入缓冲区后,便唤醒进程B;反之,当缓冲区已满时,进程A 因没有缓冲区放数据而阻塞,进程B 将缓冲区数据取走后便唤醒A。
+
+**17.为什么进程在进入临界区之前应先执行“进入区”代码?而在退出前又要执行“退出区”代码?**
+
+答:为了实现多个进程对临界资源的互斥访问,必须在临界区前面增加一段用于检查欲访问的临界资源是否正被访问的代码,如果未被访问,该进程便可进入临界区对资源进行访问,并设置正被访问标志,如果正被访问,则本进程不能进入临界区,实现这一功能的代码为"进入区"代码;在退出临界区后,必须执行"退出区"代码,用于恢复未被访问标志,使其它进程能再访问此临界资源。
+
+**18. 同步机构应遵循哪些基本准则?为什么?**
+
+答:同步机构应遵循的基本准则是:空闲让进、忙则等待、有限等待、让权等待
+
+原因:为实现进程互斥进入自己的临界区。
+
+**19. 试从物理概念上说明记录型信号量wait 和signal。**
+
+1. wait(S):当S.value>0时,表示目前系统中这类资源还有可用的。执行一次wait 操作,意味着进程请求一个单位的该类资源,使系统中可供分配的该类资源减少一个,因此描述为S.value:=S.value-1;当S.value<0时,表示该类资源已分配完毕,进程应调用block原语自我阻塞,放弃处理机,并插入到信号量链表S.L中。
+
+2. signal(S):执行一次signal操作,意味着释放一个单位的可用资源,使系统中可供分配的该类资源数增加一个,故执行S.value:=S.value+1 操作。若加1后S.value≤0,则表示在该信号量链表中,仍有等待该资源的进程被阻塞,因此应调用wakeup 原语,将S.L链表中的第一个等待进程唤醒。
+
+**20.你认为整型信号量机制是否完全遵循了同步机构的四条准则?**
+
+答:整型信号量机制不完全遵循同步机制的四条准则,它不满足“让权等待”准则。
+
+**21.如何利用信号量机制来实现多个进程对临界资源的互斥访问?并举例说明之。**
+
+答:为使多个进程互斥访问某临界资源,只需为该资源设置一互斥信号量mutex,并设其初值为1,然后将各进程访问该资源的临界区CS置于wait(mutex)和signal(mutex)操作之间即可。这样,每个欲访问该临界资源的进程在进入临界区之前,都要先对mutex 执行wait 操作,若该资源此刻未被访问,本次wait 操作必然成功,进程便可进入自己的临界区,这时若再有其他进程也欲进入自己的临界区,此时由于对mutex 执行wait操作定会失败,因而该进程阻塞,从而保证了该临界资源能被互斥访问。当访问临界资源的进程退出临界区后,应对mutex执行signal 操作,释放该临界资源。利用信号量实现进程互斥的进程描述
+
+如下:
+
+```cpp
+Var mutex: semaphore:=1;
+begin
+parbegin
+ process 1: begin
+ repeat
+ wait(mutex);
+ critical section
+ signal(mutex);
+ remainder section
+ until false;
+ end
+
+ process 2: begin
+ repeat
+ wait(mutex);
+ critical section
+ signal(mutex);
+ remainder section
+ until false;
+ end
+parend
+end
+```
+
+**22.试写出相应的程序来描述图2-17所示的前驱图。**
+
+答:(a)Var a, b, c, d, e, f, g, h; semaphore:= 0, 0,0, 0, 0, 0, 0, 0;
+
+```cpp
+begin
+parbegin
+ begin S1; signal(a); signal(b); end;
+ begin wait(a); S2; signal(c); signal(d); end;
+ begin wait(b); S3; signal(e); end;
+ begin wait(c); S4; signal(f); end;
+ begin wait(d); S5; signal(g); end;
+ begin wait(e); S6; signal(h); end;
+ begin wait(f); wait(g); wait(h); S7; end;
+parend
+end
+```
+
+(b)Var a, b, c, d, e, f, g, h, i, j; semaphore:= 0,0, 0, 0, 0, 0, 0,0,0, 0;
+
+```cpp
+begin
+parbegin
+ begin S1; signal(a); signal(b); end;
+ begin wait(a); S2; signal(c); signal(d); end;
+ begin wait(b); S3; signal(e); signal(f); end;
+ begin wait(c); S4; signal(g); end;
+ begin wait(d); S5; signal(h); end;
+ begin wait(e); S6; signal(i); end;
+ begin wait(f); S7; signal(j); end;
+ begin wait(g);wait(h); wait(i); wait(j); S8;end;
+parend
+end
+```
+
+**23.在生产者消费者问题中,如果缺少了signal(full)或signal(empty),对执行结果有何影响?**
+
+如果缺少signal(full),那么表明从第一个生产者进程开始就没有改变信号量full 值,即使缓冲池产品已满,但full值还是0,这样消费者进程执行wait(full)时认为缓冲池是空而取不到产品,消费者进程一直处于等待状态。
+
+如果缺少signal(empty),在生产者进程向n个缓冲区投满产品后消费者进程才开始从中取产品,这时empty=0,full=n,那么每当消费者进程取走一个产品empty值并不改变,直到缓冲池取空了,empty 值也是0,即使目前缓冲池有n 个空缓冲区,生产者进程要想再往缓冲池中投放产品也会因为申请不到空缓冲区被阻塞。
+
+**24.在生产消费者问题中,如果将两个wait操作即wait(full)和wait(mutex)互换位置,或者将signal(mutex)与signal(full)互换位置,结果如何?**
+
+答:将wait(full)和wait(mutex)互换位置后,可能引起死锁。考虑系统中缓冲区全满时,若一生产者进程先执行了wait(mutex)操作并获得成功,则当再执行wait(empty)操作时,它将因失败而进入阻塞状态,它期待消费者进程执行signal(empty)来唤醒自己,在此之前,它不可能执行signal(mutex)操作,从而使试图通过执行wait(mutex)操作而进入自己的临界区的其他生产者和所有消费者进程全部进入阻塞状态,这样容易引起系统死锁。若signal(mutex)和signal(full)互换位置后只是影响进程对临界资源的释放次序,而不会引起系统死锁,因此可以互换位置。
+
+**25.我们在为某一临界资源设置一把锁W,当W=1时表示关锁,当W=0时表示锁已打开。**
+
+**试写出开锁和关锁的原语,并利用他们实现互斥。**
+
+```cpp
+// 整型信号量:
+lock(W): while W=1 do no-op
+W:=1;
+unlock(W): W:=0;
+
+// 记录型信号量:
+lock(W): W:=W+1;
+if(W>1) then block(W, L)
+unlock(W): W:=W-1;
+if(W>0) then wakeup(W, L)
+
+// 例子:
+Var W:semaphore:=0;
+begin
+ repeat
+ lock(W);
+ critical section
+ unlock(W);
+ remainder section
+ until false;
+end
+```
+
+**26.试修改下面生产者-消费者问题解法中的错误:**
+
+```cpp
+producer:
+begin
+repeat
+ …
+ producer an item in nextp;
+ wait(mutex);
+ wait(full); // 应为wait(empty), 而且还应该在wait(mutex)前
+ buffer(in):=nextp; // 缓冲池数组游标应前移:in:=(in+1) mod n
+ signal(mutex); // signal(mutex)
+until false;
+end
+
+consumer:
+begin
+repeat
+ wait(mutex);
+ wait(empty) // 应为wait(full), 而且还应该在wait(mutex)前
+ nextc:=buffer(out);
+ out:=out+1; // 考虑循环,应改为:out:=(out+1) mod n
+ signal(mutex) // signal(empty)
+ consumer item in nextc;
+until false;
+end
+```
+
+**27.试利用记录型信号量写出一个不会出现死锁的哲学家进餐问题的算法.**
+
+```cpp
+Var chopstick:array[0,…,4] of semaphore;
+// 所有信号量均被初始化为1,第i 位哲学家的活动可描述为:
+Repeat
+ Wait(chopstick[i]);
+ Wait(. chopstick[(i+1) mod 5]);
+ …
+ Ea.t ;
+ …
+ Signal(chopstick[i]);
+ Signal(chopstick[(i+1) mod 5])
+ Ea.t ;
+ …
+ Think;
+Until false;
+```
+
+**28.在测量控制系统中的数据采集任务,把所采集的数据送一单缓冲区;计算任务从该单缓冲中取出数据进行计算.试写出利用信号量机制实现两者共享单缓冲的同步算法。**
+
+```cpp
+a. Var mutex, empty, full: semaphore:=1, 1, 0;
+gather:
+begin
+repeat
+ ……
+ gather data in nextp;
+ wait(empty);
+ wait(mutex);
+ buffer:=nextp;
+ signal(mutex);
+ signal(full);
+until false;
+end
+
+compute:
+begin
+repeat
+ ……
+ wait(full);
+ wait(mutex);
+ nextc:=buffer;
+ signal(mutex);
+ signal(empty);
+ compute data in nextc;
+until false;
+end
+
+
+b. Var empty, full: semaphore:=1, 0;
+gather:
+begin
+repeat
+ ……
+ gather data in nextp;
+ wait(empty);
+ buffer:=nextp;
+ signal(full);
+until false;
+end
+
+compute:
+begin
+repeat
+ ……
+ wait(full);
+ nextc:=buffer;
+ signal(empty);
+ compute data in nextc;
+until false;
+end
+```
+
+**29.画图说明管程由哪几部分组成,为什么要引入条件变量?**
+
+答:管程由四部分组成:①管程的名称;②局部于管程内部的共享数据结构说明;③对该数据结构进行操作的一组过程;④对局部于管程内部的共享数据设置初始值的语句;当一个进程调用了管程,在管程中时被阻塞或挂起,直到阻塞或挂起的原因解除,而在此期间,如果该进程不释放管程,则其它进程无法进入管程,被迫长时间地等待。为了解决这个问题,引入了条件变量condition。
+
+**30.如何利用管程来解决生产者与消费者问题?**
+
+答:首先建立一个管程,命名为ProclucerConsumer,包括两个过程:
+
+(1)Put(item)过程。生产者利用该过程将自己生产的产品放到缓冲池,用整型变量count表示在缓冲池中已有的产品数目,当count≥n 时,表示缓冲池已满,生产者须等待。
+
+(2)get(item)过程。消费者利用该过程从缓冲池中取出一个产品,当count≤0时,表示缓冲池中已无可取的产品,消费者应等待。PC 管程可描述如下:
+
+```cpp
+type producer-consumer=monitor
+Var in,out,count:integer;
+buffer:array[0,…,n-1]of item;
+notfull,notempty:condition;
+
+procedure entry dot(item)
+begin
+ if count>=n then not full.wait;
+ buffer(in):=nextp;
+ in:=(in+1)mod n;
+ count:=count+1;
+ if notempty.queue then notempty.signal;
+end
+
+procedure entry get(item)
+begin
+ if count<=0 then not full.wait;
+ nextc:=buffer(out);
+ out:=(out+1)mod n;
+ count:=count-1;
+ if notfull.quene then notfull.signal;
+end
+
+begin in:=out:=0;
+count:=0
+end
+
+// 在利用管程解决生产者一消费者问题时,其中的生产者和消费者可描述为:
+producer: begin
+repeat
+ produce an inem in nestp
+ PC.put(item);
+until false;
+end
+
+consumer: begin
+repeat
+ PC.get(item);
+ consume the item in enxtc;
+until false;
+end
+```
+
+**31.什么是AND信号量?试利用AND信号量写出生产者一消费者问题的解法。**
+
+答:为解决并行带来的死锁问题,在wait 操作中引入AND 条件,其基本思想是将进程在整个运行过程中所需要的所有临界资源,一次性地全部分配给进程,用完后一次性释放。解决生产者-消费者问题可描述如下:
+
+```cpp
+var mutex,empty,full: semaphore:=1,n,0;
+buffer: array[0,...,n-1] of item;
+in,out: integer:=0,0;
+begin
+parbegin
+ producer: begin
+ repeat
+ produce an item in nextp;
+ wait(empty);
+ wait(s1,s2,s3,...,sn); //s1,s2,...,sn为执行生产者进程除empty外其余的条件
+ wait(mutex);
+ buffer(in):=nextp;
+ in:=(in+1) mod n;
+ signal(mutex);
+ signal(full);
+ signal(s1,s2,s3,...,sn);
+ until false;
+ end
+
+ consumer: begin
+ repeat
+ wait(full);
+ wait(k1,k2,k3,...,kn); //k1,k2,...,kn 为执行消费者进程除full外其余的条件
+ wait(mutex);
+ nextc:=buffer(out);
+ out:=(out+1) mod n;
+ signal(mutex);
+ signal(empty);
+ signal(k1,k2,k3,...,kn);
+ consume the item in nextc;
+ until false;
+ end
+parend
+end
+```
+
+**32.什么是信号量集?试利用信号量集写出读者一写者问题的解法。**
+
+答:对AND信号量加以扩充,形成的信号量集合的读写机制。
+
+```cpp
+Var RN integer;
+L,mx: semaphore:=RN,1;
+begin
+parbegin
+ reader:begin
+ repeat
+ Swait(L,1,1);
+ Swait(mx,1,1);
+ perform read operation;
+ Ssignal(L,1);
+ until false
+ end
+ writer:begin
+ repeat
+ Swait(mx,1,1;L,RN,0);
+ perform write operation;
+ Ssignal(mx,1);
+ until false
+ end
+parend
+end
+```
+
+**33.试比较进程间的低级与高级通信工具。**
+
+答:用户用低级通信工具实现进程通信很不方便,效率低,通信对用户不透明,所有操作都必须由程序员来实现,而高级通信工具弥补了这些缺陷,用户直接利用操作系统提供的一组通信命令,高效地传送大量的数据。
+
+**34.当前有哪几种高级通信机制?**
+
+答:共享存储器系统、消息传递系统以及管道通信系统。
+
+**35.消息队列通信机制有哪几方面的功能?**
+
+答:(1)构成消息(2)发送消息(3)接收梢息(4)互斥与同步。
+
+**36.为什么要在OS中引入线程?**
+
+答:在操作系统中引入线程,则是为了减少程序在并发执行时所付出的时空开销,使OS具有更好的并发性,提高CPU的利用率。进程是分配资源的基本单位,而线程则是系统调度的基本单位。
+
+**37.试说明线程具有哪些属性?**
+
+答:(1)轻型实体(2)独立调度和分派的基本单位(3)可并发执行(4)共享进程资源。
+
+**38.试从调度性,并发性,拥有资源及系统开销方面对进程和线程进行比较。**
+
+1. 调度性。线程在OS中作为调度和分派的基本单位,进程只作为资源拥有的基本单位。
+2. 并发性。进程可以并发执行,一个进程的多个线程也可并发执行。
+3. 拥有资源。进程始终是拥有资源的基本单位,线程只拥有运行时必不可少的资源,本身基本不拥有系统资源,但可以访问隶属进程的资源。
+4. 系统开销。操作系统W在创建、撤消和切换进程时付出的开销显著大于线程。
+
+**39. 为了在多线程OS中实现进程之间的同步与通信,通常提供了哪几种同步机制?**
+
+答:同步功能可以控制程序流并访问共享数据,从而并发执行多个线程。共有四种同步模型:互斥锁、读写锁、条件变量和信号。
+
+**40.用于实现线程同步的私用信号量和公用信号量之间有何差别?**
+
+1. 私用信号量。当某线程需利用信号量实现同一进程中各线程之间的同步时,可调用创建信号量的命令来创建一个私用信号量,其数据结构存放在应用程序的地址空间中。
+2. 公用信号量。公用信号量是为实现不同进程间或不同进程中各线程之间的同步而设置的。其数据结构是存放在受保护的系统存储区中,由OS为它分配空间并进行管理。
+
+**41.何谓用户级线程和内核支持线程?**
+
+1. 用户级线程:仅存在于用户空间中的线程,无须内核支持。这种线程的创建、撤销、线程间的同步与通信等功能,都无需利用系统调用实现。用户级线程的切换通常发生在一个应用进程的诸多线程之间,同样无需内核支持。
+
+2. 内核支持线程:在内核支持下运行的线程。无论是用户进程中的线程,还是系统线程中的线程,其创建、撤销和切换等都是依靠内核,在内核空间中实现的。在内核空间里还为每个内核支持线程设置了线程控制块,内核根据该控制块感知某线程的存在并实施控制。
+
+**42.试说明用户级线程的实现方法。**
+
+答:用户级线程是在用户空间中的实现的,运行在“运行时系统”与“内核控制线程”的中间系统上。运行时系统用于管理和控制线程的函数的集合。内核控制线程或轻型进程LWP可通过系统调用获得内核提供服务,利用LWP进程作为中间系统。
+
+**43.试说明内核支持线程的实现方法。**
+
+答:系统在创建新进程时,分配一个任务数据区PTDA,其中包括若干个线程控制块TCB空间。创建一个线程分配一个TCB,有关信息写入TCB,为之分配必要的资源。当PTDA中的TCB用完,而进程又有新线程时,只要所创建的线程数目未超过系统允许值,系统可在为之分配新的TCB;在撤销一个线程时,也应回收线程的所有资源和TCB。
+
+## 第三章 处理机调度与死锁
+
+**1.高级调度与低级调度的主要任务是什么?为什么要引入中级调度?**
+
+答:高级调度的主要任务是根据某种算法,把外存上处于后备队列中的那些作业调入内存。低级调度是保存处理机的现场信息,按某种算法先取进程,再把处理器分配给进程。引入中级调度的主要目的是为了提高内存利用率和系统吞吐量。使那些暂时不能运行的进程不再占用内存资源,将它们调至外存等待,把进程状态改为就绪驻外存状态或挂起状态。
+
+**2.何谓作业、作业步和作业流?**
+
+1. 作业包含通常的程序和数据,还配有作业说明书。系统根据该说明书对程序的运行进行控制。批处理系统中是以作业为基本单位从外存调入内存。
+
+2. 作业步是指每个作业运行期间都必须经过若干个相对独立相互关联的顺序加工的步骤。
+
+3. 作业流是指若干个作业进入系统后依次存放在外存上形成的输入作业流;在操作系统的控制下,逐个作业进程处理,于是形成了处理作业流。
+
+**3.在什么情况下需要使用作业控制块JCB?其中包含了哪些内容?**
+
+答:每当作业进入系统时,系统便为每个作业建立一个作业控制块JCB,根据作业类型将它插入到相应的后备队列中。
+
+JCB 包含的内容通常有:1)作业标识 2)用户名称 3)用户账户 4)作业类型(CPU繁忙型、I/O芳名型、批量型、终端型) 5)作业状态 6)调度信息(优先级、作业已运行) 7)资源要求 8)进入系统时间 9)开始处理时间 10)作业完成时间 11)作业退出时间 12)资源使用情况等
+
+**4.在作业调度中应如何确定接纳多少个作业和接纳哪些作业?**
+
+答:作业调度每次接纳进入内存的作业数,取决于多道程序度。应将哪些作业从外存调入内存,取决于采用的调度算法。最简单的是先来服务调度算法,较常用的是短作业优先调度算法和基于作业优先级的调度算法。
+
+**5.试说明低级调度的主要功能。**
+
+答:(1)保存处理机的现场信息(2)按某种算法选取进程(3)把处理机分配给进程。
+
+**6.在抢占调度方式中,抢占的原则是什么?**
+
+答:抢占的原则有:时间片原则、优先权原则、短作业优先权原则等。
+
+**7.在选择调度方式和调度算法时,应遵循的准则是什么?**
+
+1. 面向用户的准则:周转时间短、响应时间快、截止时间的保证、优先权准则。
+
+2. 面向系统的准则:系统吞吐量高、处理机利用率好、各类资源的平衡利用。
+
+**8.在批处理系统、分时系统和实时系统中,各采用哪几种进程(作业)调度算法?**
+
+1. 批处理系统的调度算法:短作业优先、优先权、高响应比优先、多级反馈队列调度算法。
+
+2. 分时系统的调度算法:时间片轮转法。
+
+3. 实时系统的调度算法:最早截止时间优先即EDF、最低松弛度优先即LLF算法。
+
+**9.何谓静态和动态优先级?确定静态优先级的依据是什么?**
+
+静态优先级是指在创建进程时确定且在进程的整个运行期间保持不变的优先级。
+
+动态优先级是指在创建进程时赋予的优先权,可以随进程推进或随其等待时间增加而改变的优先级,可以获得更好的调度性能。
+
+确定进程优先级的依据:进程类型、进程对资源的需求和用户要求。
+
+**10.试比较FCFS和SPF两种进程调度算法。**
+
+相同点:两种调度算法都可以用于作业调度和进程调度。
+
+不同点:FCFS调度算法每次都从后备队列中选择一个或多个最先进入该队列的作业,将它们调入内存、分配资源、创建进程、插入到就绪队列。该算法有利于长作业/进程,不利于短作业/进程。SPF算法每次调度都从后备队列中选择一个或若干个估计运行时间最短的作业,调入内存中运行。该算法有利于短作业/进程,不利于长作业/进程。
+
+**11.在时间片轮转法中,应如何确定时间片的大小?**
+
+答:时间片应略大于一次典型的交互需要的时间。一般应考虑三个因素:系统对相应时间的要求、就绪队列中进程的数目和系统的处理能力。
+
+**12.通过一个例子来说明通常的优先级调度算法不能适用于实时系统?**
+
+答:实时系统的调度算法很多,主要是基于任务的开始截止时间和任务紧急/松弛程度的任务优先级调度算法,通常的优先级调度算法不能满足实时系统的调度实时性要求而不适用。
+
+**13.为什么说多级反馈队列调度算法能较好地满足各方面用户的需求?**
+
+1. 终端型作业用户提交的作业大多属于较小的交互型作业,系统只要使这些作业在第一队列规定的时间片内完成,终端作业用户就会感到满足。
+
+2. 短批处理作业用户,开始时像终端型作业一样,如果在第一队列中执行一个时间片段即可完成,便可获得与终端作业一样的响应时间。对于稍长作业,通常只需在第二和第三队列各执行一时间片即可完成,其周转时间仍然较短。
+
+3. 长批处理作业,它将依次在第1,2,…,n个队列中运行,然后再按轮转方式运行,用户不必担心其作业长期得不到处理。所以,多级反馈队列调度算法能满足多用户需求。
+
+**14.为什么在实时系统中,要求系统(尤其是CPU)具有较强的处理能力?**
+
+答:实时系统中通常有着多个实时任务。若处理机的处理能力不够强,有可能因为处理机忙不过来而使某些实时任务得不到及时处理,导致发生难以预料的后果。
+
+**15.按照调度方式可将实时调度算法分为哪几种?**
+
+答:可分为非抢占式和抢占式两种算法。而非抢占式算法又分为非抢占式轮转和优先调度算法;抢占式调度算法又分为基于时钟中断的抢占式优先权和立即抢占式优先权调度算法。
+
+**16.什么是最早截止时间优先调度算法?举例说明。**
+
+答:根据任务的开始截止时间确定的任务优先级调度算法。截止时间越早则优先级越高。该算法要求在系统中保持一个实时任务就绪队列,该队列按各任务截止时间的先后排序。
+
+举例:非抢占式调度方式用于非周期实时任务。图3-9是将该算法用于非抢占调度方式之例。该例中具有四个非周期任务,它们先后到达。系统首先调度任务1执行,在任务1执行期间,任务2、3又先后到达。由于任务3的开始截止时间早于任务2,故系统在任务1后将调度任务3执行。在此期间又到达作业4,其开始截止时间仍是早于任务2的,故在任务3执行完后,系统又调度任务4执行,最后才调度任务2执行。
+
+图3-9 EDF算法用于非抢占调度的调度方式
+
+**17.什么是最低松弛度优先调度算法?举例说明之。**
+
+答:该算法是根据任务紧急(或松弛)的程度,来确定任务的优先级。任务的紧急程度愈高,为该任务所赋予的优先级就愈高,以使之优先执行。例如,一个任务在200 ms 时必须完成,而它本身所需的运行时间就有100 ms,因此,调度程序必须在100 ms 之前调度执行,该任务的紧急程度(松弛程度)为100 ms。又如,另一任务在400 ms 时必须完成,它本身需要运行 150 ms,则其松弛程度为 250 ms。
+
+**18.何谓死锁?产生死锁的原因和必要条件是什么?**
+
+答:死锁是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。产生死锁的原因为竞争资源和进程间推进顺序非法。其必要条件是:互斥条件、请求和保持条件、不剥夺条件、环路等待条件。
+
+**19.在解决死锁问题的几个方法中,哪种方法最易于实现?哪种方法使资源利用率最高?**
+
+答:解决死锁的四种方法即预防、避免、检测和解除死锁中,预防死锁最容易实现;避免死锁使资源的利用率最高。
+
+**20.请详细说明可通过哪些途径预防死锁。**
+
+1. 摈弃“请求和保持”条件,就是如果系统有足够资源,便一次性把进程需要的所有资源分配给它;
+
+2. 摈弃“不剥夺”条件,就是已经拥有资源的进程,当它提出新资源请求而不能立即满足时,必须释放它已保持的所有资源,待以后需要时再重新申请;
+
+3. 摈弃“环路等待”条件,就是将所有资源按类型排序标号,所有进程对资源的请求必须严格按序号递增的次序提出。
+
+**21.在银行家算法的例子中,如果P0发出请求向量由Request(0,2,0)改为Request(0,1,0),问系统可否将资源分配给它?**
+
+(此答案有点问题,需重新考虑)
+
+1. 可以。银行家算法各种资源数量分别为10、5、7,在T0时刻的资源分配如图所示:
+
+2. 具体分析如下:
+
+ ①Requst0(0,1,0)<=Need0(7,4,3);
+ ②Requst0(0,1,0)<=Available(2,3,0);
+ 系统先假定可为P0分配资源,并修改Available**0**,Allocation**0**和Need**0**向量,由此形成的资源变化情况如下图所示:
+
+3. P0请求资源:P0发出请求向量Requst0(0,1,0),系统按银行家算法进行检查:
+
+ ①Requst0(0,1,0)<=Need0(7,4,3);
+ ②Requst0(0,1,0)<=Available(2,3,0);
+ ③系统暂时先假定可为P0分配资源,并修改有关数据,如下图所示
+
+综上所述系统可以将资源分配给它。
+
+**22.银行家算法中出现以下资源分配,试问(1)该状态是否安全?(2)若进程P2提出Request(1,2,2,2)后,系统能否将资源分配给它?**
+
+(1)安全,因为存在安全序列{P0,P3,P4,P1,P2}
+
+(参考答案有错)
+(2)系统能分配资源,分析如下。
+① Request(1,2,2,2) <=Need2(2,3,5,6);
+② Request(1,2,2,2) <=Available2(1,3,5,4)改成Available2(1,6,2,2);
+③ 系统先假定可为P2分配资源,并修改Available2,Allocation2和Need2向量,
+由此形成的资源变化情况如下图所示:
+④ 再利用安全性算法检查此时系统是否安全。如下图
+由此进行的安全性检查得知,可以找到一个安全序列{P2,P0,P1,P3,P4}。
+
+## 第四章
+
+**1.为什么要配置层次式存储器?**
+
+答:设置多个存储器可以使存储器两端的硬件能并行工作;采用多级存储系统,特别是Cache技术,是减轻存储器带宽对系统性能影响的最佳结构方案;在微处理机内部设置各种缓冲存储器,减轻对存储器存取的压力。增加CPU中寄存器数量大大缓解对存储器压力。
+
+**2.可采用哪几种方式将程序装入内存?它们分别适用于何种场合?**
+
+1. 绝对装入方式,只适用于单道程序环境。
+
+2. 可重定位装入方式,适用于多道程序环境。
+
+3. 动态运行时装入方式,用于多道程序环境;不允许程序运行时在内存中移位置。
+
+**3.何谓静态链接?何谓装入时动态链接和运行时的动态链接(P120)?**
+
+1. 静态链接是指在程序运行前,先将各目标模块及它们所需的库函数,链接成一个完整的装配模块,以后不再拆开的链接方式。
+
+2. 装入时动态链接是指将用户源程序编译后得到的一组目标模块,在装入内存时采用边装入边链接的链接方式。
+
+3. 运行时动态链接是指对某些目标模块的链接,是在程序执行中需要该目标模块时,才对它进行的链接。
+
+**4.在进行程序链接时,应完成哪些工作?**
+
+答:由链接程序Linker将编译后形成的一组目标模块,以及它们需要的库函数链接在一起,形成一个完整的装入模块Load Module。主要工作是修改程序内的相对地址和修改目标程序中的外部调用标号。
+
+**5.在动态分区分配方式中,应如何将各空闲分区链接成空闲分区链?**
+
+答:在每个分区的起始部分,设置一些控制分区分配的信息,以及用于链接各分区所用的前向指针;在分区尾部设置一个后向指针,通过前后向链接指针,将所有空闲分区链成一个双向链。当分区分配出去后,把状态位由“0”改为“1”。
+
+**6.为什么要引入动态重定位?如何实现?**
+
+答:在程序执行过程中,每当访问指令或数据时,将要访问的程序或数据的逻辑地址转换成物理地址,引入了动态重定位;具体实现方法是在系统中增加一个重定位寄存器,用来装入程序在内存中的起始地址,程序执行时,真正访问的内存地址是相对地址与重定位寄存器中的地址相加之和,从而实现动态重定位。
+
+**7.在采用首次适应算法回收内存时,可能出现哪几种情况?应怎样处理这些情况?**
+
+答:在采用首次适应算法回收内存时可能出现4种情况:
+
+1. 回收区前邻空闲区。将回收区与前邻空闲区合并,将前邻空闲区大小修改为两者之和。
+
+2. 回收区后邻空闲区。将两区合并,改后邻空闲区始址为回收区始址,大小为两者之和。
+
+3. 回收区前后均邻空闲区。将三个分区合并,修改前邻空闲区大小为三者之和。
+
+4. 回收区前后均不邻空闲区。为回收区设置空闲区表项,填入回收区始址和大小并插入空闲区队列。
+
+**8.令 表示大小为 、地址为x 的块的伙伴系统地址,试写出的通用表达式。**
+
+答:当 时, ;当 时,
+
+**9.分区存储管理中常用那些分配策略?比较它们的优缺点。**
+
+答:分区存储管理中的常用分配策略:首次适应算法、循环首次适应算法、最佳适应算法、最坏适应算法。
+
+首次适应算法优缺点:保留了高址部分的大空闲区,有利于后来的大型作业分配;低址部分不断被划分,留下许多难以利用的小空闲区,每次查找都从低址开始增加了系统开销。
+
+循环首次适应算法优缺点:内存空闲分区分布均匀,减少了查找系统开销;缺乏大空闲分区,导致不能装入大型作业。
+
+最佳适应算法优缺点:每次分配给文件的都是最适合该文件大小的分区,内存中留下许多难以利用的小空闲区。
+
+最坏适应算法优缺点:剩下空闲区不太小,产生碎片几率小,对中小型文件分配分区操作有利;存储器中缺乏大空闲区,对大型文件分区分配不利。
+
+**10.在系统中引入对换后可带来哪些好处?**
+
+答:交换技术将暂不需要的作业移到外存,让出内存空间以调入其它作业,交换到外存的作业也可以被再次调入。目的是解决内存紧张问题,带来的好处是进一步提高了内存利用率和系统吞吐量。
+
+**11.为实现对换,系统应具备哪几方面的功能?**
+
+答:系统应具备三方面功能:对换空间管理,进程换出,进程换入。
+
+**12.在以进程为单位进行对换时,每次是否都将整个进程换出?为什么?**
+
+答:在以进程为单位进行对换时,并非每次都将整个进程换出。这是因为:
+
+1. 从结构上讲,进程由程序段、数据段和进程控制块组成的,其中进程控制块总有部分或全部常驻内存,不被换出。
+
+2. 程序段和数据段可能正被若干进程共享,此时它们也不能换出。
+
+**13.为实现分页存储管理,需要哪些硬件的支持?**
+
+答:动态重定位技术、虚拟存储技术、多道程序设计技术。
+
+**14.较详细的说明引入分段存储管理是为了满足用户哪几方面的需要。**
+
+1. 方便编程。用户通常把自己的作业按照逻辑关系划分为若干段,每段都从0编址,并有自己名字和长度。因此,希望要访问的逻辑地址是由段名和段内偏移量决定。
+
+2. 信息共享。在实现对程序和数据的共享时,是以信息逻辑单位为基础。分页系统中的页是存放信息的物理单位,无完整意义,不便于共享;段是信息的逻辑单位。为了实现段的共享,希望存储管理能与用户程序分段的组织方式相适应。
+
+3. 信息保护。对信息的逻辑单位进行保护,分段能更有效方便地实现信息保护功能。
+
+4. 动态增长。在实际应用中,有些段特别是数据段,在使用过程中会不断增长,事先又无法确切知道增长多少。分段存储管理方式能较好解决这个问题。
+
+5. 动态链接。运行时先将主程序对应的目标程序装入内存并启动运行,运行过程中又需要调用某段时,才将该段调入内存链接。所以动态链接也要求以段作为管理单位。
+
+**15.在具有快表的段页式存储管理方式中,如何实现地址变换?**
+
+答:在CPU给出有效地址后,由地址变换机构自动将页号P送入高速缓冲寄存器,并将此页号与高速缓存中的所有页号比较,若找到匹配页号,表示要访问的页表项在快表中。可直接从快表读出该页对应物理块号,送到物理地址寄存器中。如快表中没有对应页表项,则再访问内存页表,找到后,把从页表项中读出物理块号送地址寄存器;同时修改快表,将此页表项存入快表。但若寄存器已满,则OS必须找到合适的页表项换出。
+
+**16.为什么说为什么说分段系统比分页系统更易于实现信息的共享和保护?**
+
+答:分页系统的每个页面是分散存储的,为了实现信息共享和保护,页面之间需要一一对应,为此需要建立大量的页表项;而分段系统的每个段都从0编址,并采用一段连续的地址空间,在实现共享和保护时,只需为要共享和保护的程序设置一个段表项,将其中的基址与内存地址一一对应就能够实现。
+
+**17.分段和分页存储管理有何区别?**
+
+1. 页是信息的物理单位,分页是为了实现离散分配方式,以消减内存的外部零头,提高内存利用率。段则是信息的逻辑单位,它含有一组相对完整的信息。
+
+2. 页的大小固定且由系统决定,由系统把逻辑地址划分为页号和页内地址两部分,是由机械硬件实现的,因而在系统中只能有一种大小的的页面;而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对原程序进行编译时,根据信息的性质来划分。
+
+3. 分页的作业地址空间是一维的,而分段作业地址空间则是二维的。
+
+**18.试全面比较连续分配和离散分配方式.**
+
+1. 连续分配是指为一个用户程序分配一个连续的地址空间,包括单一和分区两种分配方式。单一方式将内存分为系统区和用户区,最简单,只用于单用户单任务操作系统;分区方式分固定和动态分区。
+
+2. 离散分配方式分为分页、分段和段页式存储管理。分页式存储管理旨在提高内存利用率,分段式存储管理旨在满足用户(程序员)的需要,段页式存储管理则将两者结合起来,具有分段系统便于实现、可共享、易于保护和动态链接等优点,又能像分页系统很好解决外部碎片及为各段可离散分配内存等问题,是比较有效的存储管理方式;
+
+**19.虚拟存储器有哪些特征?其中最本质的特征是什么?**
+
+答:虚拟存储器有多次性、对换性、虚拟性三大特征。最本质的特征是虚拟性。
+
+**20.实现虚拟存储器需要哪些硬件支持?**
+
+答:(1)请求分页(段)的页(段)表机制(2)缺页(段)中断机构(3)地址变换机构
+
+**21.实现虚拟存储器需要哪几个关键技术?**
+
+1. 在分页请求系统中是在分页的基础上,增加了请求调页功能和页面置换功能所形成的页式虚拟存储系统。允许只装入少数页面的程序(及数据),便启动运行。
+
+2. 在请求分段系统中是在分段系统的基础上,增加了请求调段及分段置换功能后形成的段式虚拟存储系统。允许只装入少数段(而非所有段)的用户程序和数据,即可启动运行。
+
+**22.在请求分页系统中,页表应包括哪些数据项?每项的作用是什么?**
+
+答:页表应包括:页号、物理块号、状态位P、访问字段A、修改位M和外存地址。其中状态位P指示该页是否调入内存,供程序访问时参考;访问字段A用于记录本页在一段时间内被访问的次数,或最近已有多长时间未被访问,提供给置换算法选择换出页面时参考;修改位M表示该页在调入内存后是否被修改过;外存地址用于指出该页在外存上的地址,通常是物理块号,供调入该页时使用。
+
+**23.在请求分页系统中,应从何处将所需页面调入内存?**
+
+答:请求分页系统中的缺页从何处调入内存分三种情况:
+
+1. 系统拥有足够对换区空间时,可以全部从对换区调入所需页面,提高调页速度。在进程运行前将与该进程有关的文件从文件区拷贝到对换区。
+
+2. 系统缺少足够对换区空间时,不被修改的文件直接从文件区调入;当换出这些页面时,未被修改的不必换出,再调入时,仍从文件区直接调入。对于可能修改的,在换出时便调到对换区,以后需要时再从对换区调入。
+
+3. UNIX方式。未运行页面从文件区调入。曾经运行过但被换出页面,下次从对换区调入。UNIX系统允许页面共享,某进程请求的页面有可能已调入内存,直接使用不再调入。
+
+**24.在请求分页系统中,常采用哪几种页面置换算法?**
+
+答:采用的页面置换算法有:最佳置换算法和先进先出置换算法,最近最久未使用(LRU)置换算法,Clock置换算法,最少使用置换算法,页面缓冲算法等。
+
+**25.在请求分页系统中,通常采用哪种页面分配方式?为什么?**
+
+答:固定分配方式是基于进程的类型(交互型)或根据程序员、系统管理员的建议,为每个进程分配固定页数的内存空间,整个运行期间不再改变;采用可变分配方式有全局置换和局部置换两种,前者易于实现,后者效率高。
+
+**26.在一个请求分页系统中,采用LRU 页面置换算法时,假如一个作业的页面走向为4 , 3 , 2 ,1 , 4 , 3 , 5 , 4 ,3 , 2 , 1 ,5,当分配给该作业的物理块数M分别为3和4时,试计算访问过程中所发生的缺页次数和缺页率 ? 比较所得结果?**
+
+答:当分配给该作业的物理块数M为3时,缺页9次,缺页率: 9/12=3/4;
+
+当分配给该作业的物理块数M为4时,缺页10次,缺页率: 10/12=5/6.
+
+**27.实现LRU算法所需的硬件支持是什么?**
+
+答:需要寄存器和栈等硬件支持。寄存器用于记录某进程在内存中各页的使用情况,栈用于保存当前使用的各个页面的页面号。
+
+**28.试说明改进型 Clock 置换算法的基本原理.**
+
+答:因为修改过的页面在换出时付出的开销比未被修改过的页面大,在改进型Clock算法中,既考虑页面的使用情况,还要增加置换代价的因素;在选择页面作为淘汰页面时,把同时满足未使用过和未被修改作为首选淘汰页面。
+
+**29.说明请求分段系统中的缺页中断处理过程。**
+
+答:请求分段系统中的缺页中断处理过程描述如下:
+
+1. 根据当前执行指令中的逻辑地址查页表,判断该页是否在主存储器中
+
+2. 该页标志为“0”形成缺页中断,中断装置通过交换PSW让操作系统的中断处理程序占用处理器。
+
+3. 操作系统处理缺页中断处理的办法是查主存分配表找一个空闲的主存块,查页表找出该页在磁盘上位置,启动磁盘读出该页信息。
+
+4. 把从磁盘上读出的信息装入找到的主存块中。
+
+5. 当页面住处被装入主存后,应修改页表中对应的表目,填上该页所占用的主存块把标志置为“1”,表示该页已在主存储器中
+
+6. 由于产生缺页中断时的那条指令并没执行完,所以在把页面装入之后应重新执行被中断指令。
+
+请求分段系统中的缺页中断处理过程如下图所示:
+
+**30.如何实现分段共享 ?**
+
+答:在每个进程的段表中,用相应的表项指向共享段在内存中起始地址;配置相应的数据结构作为共享段表,在段表项中设置共享进程计数Count,每调用一次该共享段,Count值增1,每当进程释放一个共享段时,Count减1,若减为0,则系统回收该共享段的物理内存,取消在共享段表中该段对应的表项;共享段应给不同的进程以不同的存取权限;不同的进程可以使用不同的段号去共享该段。
+
+## 第五章
+
+**1.试说明设备控制器的组成。**
+
+答:由设备控制器与处理机的接口,设备控制器与设备的接口与I/O逻辑组成。
+
+**2.为了实现CPU与设备控制器间的通信,设备控制器应具备哪些功能?**
+
+答:接收和识别命令;数据交换;标识和报告设备状态;地址识别;数据缓冲;差错控制。
+
+**3.什么是字节多路通道?什么是数组选择通道和数组多路通道?**
+
+1. 字节多路通道。按字节交叉方式工作的通道。通常含有许多非分配型子通道,数量从几十到数百个,每个子通道连接一台I/O设备,控制其I/O操作。子通道按时间片轮转方式共享主通道。
+
+2. 数组选择通道。按数组方式传送数据,传输速率很高,每次只允许一个设备数据。
+
+3. 数组多路通道。将数组选择通道传输速率高和字节多路通道的各子通道分时并行操作的优点结合而成。含有多个非分配型子通道,具有很高的数据传输率和通道利用率。
+
+**4.如何解决因通道不足而产生的瓶颈问题?**
+
+答:解决问题的有效方法是增加设备到主机间的通路而不增加通道,把一个设备连到多个控制器上,控制器又连到多个通道上,这种多通路方式解决了“瓶颈”问题,提高了系统可靠性,个别通道或控制器的故障不会使设备和存储器之间没有通路。
+
+**5.试对VESA 及PCI两种总线进行比较。**
+
+1. VESA总线的设计思想是以低价占领市场。总线带宽32位,最高传输速率132Mb/s。广泛用于486微机。缺点是能连接的设备数仅为2~4 台,控制器中无缓冲,难于适应处理器速度的提高,不支持Pentium机。
+
+2. PCI总线在CPU和外设间插入了复杂的管理层,协调数据传输和提供一致接口。管理层中配有数据缓冲,放大了线路的驱动能力,最多支持10种外设,支持高时钟频率的CPU运行,最大传输速率132Mb/s。可连接ISA、EISA等传统总线,又支持Pentium的64位系统,是基于奔腾等新一代微处理器而发展的总线。
+
+**6.试说明推动I/O控制发展的主要因素是什么?**
+
+答:推动I/O控制发展的主要动力在于尽量减少主机对I/O控制的干预,把主机从繁杂的I/O控制事务中解脱出来,用更多的时间和精力去完成其数据处理任务。同时,中断机制在计算机系统中的引入、DMA控制器的出现和通道研制的成功使I/O控制的发展具备了技术支持和成为可能。
+
+**7.有哪几种I/O控制方式?各适用于何种场合?**
+
+共有四种I/O控制方式。
+
+1. 程序I/O方式:早期计算机无中断机构,处理机对I/O设备的控制采用程序I/O方式或称忙等的方式。
+
+2. 中断驱动I/O控制方式:适用于有中断机构的计算机系统中。
+
+3. 直接存储器访问(DMA)I/O控制方式:适用于具有DMA控制器的计算机系统中。
+
+4. I/O通道控制方式:具有通道程序的计算机系统中。
+
+**8.试说明DMA 的工作流程。**
+
+答:以从磁盘读入数据为例,说明DMA的工作流程。当CPU要从磁盘读入数据块时,先向磁盘控制器发送一条读命令。该命令被送到命令寄存器CR中。同时还发送本次要读入数据的内存起始目标地址,送入内存地址寄存器MAR;本次要读数据的字节数送入数据计数器DC,将磁盘中的源地址直接送DMA控制器的I/O控制逻辑上。然后启动DMA 控制器传送数据,以后CPU便处理其它任务。整个数据传送过程由DMA控制器控制。下图为DMA方式的工作流程图。
+
+**9.引入缓冲的主要原因是什么?**
+
+答:引入缓冲的主要原因是:
+
+1. 缓和CPU与I/O 设备间速度不匹配的矛盾
+
+2. 减少对CPU的中断频率,放宽对中断响应时间的限制
+
+3. 提高CPU与I/O 设备之间的并行性
+
+**10.在单缓冲情况下,为什么系统对一块数据的处理时间为max(C,T)+M?**
+
+答:在块设备输入时,先从磁盘把一块数据输入到缓冲区,耗时为T;然后由操作系统将缓冲区数据送给用户区,耗时M;接下来由CPU对块数据进行计算,耗时C。在单缓冲情况下,磁盘把数据输入到缓冲区的操作和CPU对数据的计算过程可以并行展开,所以系统对每一整块数据的处理时间为max(C, T) + M。
+
+**11.为什么在双缓冲情况下,系统对一块数据的处理时间为max(T,C)?**
+
+答:写入者花费时间T 将数据写满一个缓冲区后再写另一个缓冲区;读出者花费时间M将一个缓冲区数据送到用户区后再传送另一个缓冲区数据,计算者读出用户区数据进行处理。由于将数据从缓冲区传到用户区操作必须与读用户区数据处理串行进行,而且可以与从外存传送数据填满缓冲区的操作并行。因此耗时大约为max(C+M,T)。考虑M是内存数据块的移动耗时非常短暂可以省略,因此近似地认为系统对一块数据处理时间为max(C,T)。
+
+**12.试绘图说明把多缓冲用于输出时的情况。**
+
+答:多缓冲用于输出的示意图如下:
+
+**13.试说明收容输入工作缓冲区和提取输出工作缓冲区的工作情况。**
+
+1. 收容输入工作缓冲区的工作情况为:在输入进程需要输入数据时,调用GetBuf(EmptyQueue)过程,从EmptyQueue队列的队首摘下一个空缓冲区,作为收容输入工作缓冲区Hin。然后把数据输入其中,装满后再调用PutBuf(InputQueue,Hin)过程,将该缓冲区挂在输入队列InputQueue的队尾。
+
+2. 提取输出工作缓冲区的工作情况为:当要输出数据时,调用GetBuf(OutputQueue)过程,从输出队列的队首取得一装满输出数据的缓冲区作为提取输出工作缓冲区Sout。在数据提取完后,再调用PutBuf(EmptyQueue,Sout)过程,将该缓冲区挂到空缓冲队列EmptyQueue的队尾。
+
+**14.何谓安全分配方式和不安全分配方式?**
+
+1. 安全分配方式是指每当进程发出I/O请求后,便进入阻塞状态,直到其I/O操作完成时才被唤醒。在采用这种分配策略时,一旦进程已获得某种设备资源后便阻塞,使它不可能再请求任何资源,而在它运行时又不保持任何资源。这种分配方式已经摒弃了造成死锁的“请求和保持”条件,分配是安全的。缺点是进程进展缓慢,CPU与I/O设备串行工作。
+
+2. 不安全分配方式是指进程发出I/O请求后仍继续执行,需要时又可发出第二个I/O请求、第三个I/O请求。仅当进程请求的设备已被另一个进程占有时,进程才进入阻塞状态。优点是一个进程可同时操作多个设备,进程推进迅速。缺点是分配不安全,可能具有“请求和保持”条件,可能造成死锁。因此,在设备分配程序中需增加一个功能,用于对本次的设备分配是否会发生死锁进行安全性计算,仅当计算结果表明分配安全的情况下才进行分配。
+
+**15.为何要引入设备独立性?如何实现设备独立性?**
+
+答:现代操作系统为了提高系统的可适应性和可扩展性,都实现了设备独立性或设备无关性。基本含义是应用程序独立于具体使用的物理设备,应用程序以逻辑设备名请求使用某类设备。实现了设备独立性功能可带来两方面的好处:(1)设备分配时的灵活性;(2)易于实现I/O重定向。
+
+为了实现设备的独立性,应引入逻辑设备和物理设备概念。在应用程序中,使用逻辑设备名请求使用某类设备;系统执行时是使用物理设备名。鉴于驱动程序是与硬件或设备紧密相关的软件,必须在驱动程序之上设置一层设备独立性软件,执行所有设备的公有操作、完成逻辑设备名到物理设备名的转换(为此应设置一张逻辑设备表)并向用户层(或文件层)软件提供统一接口,从而实现设备的独立性。
+
+**16.在考虑到设备的独立性时,应如何分配独占设备?**
+
+答:在考虑到设备的独立性时,应按如下步骤来分配独占设备:
+
+1. 进程以逻辑设备名提出I/O请求。
+
+2. 根据逻辑设备表获得I/O请求的逻辑设备对应物理设备在系统设备表中的指针。
+
+3. 检索系统设备表,找到属于请求类型、空闲可用且分配安全设备的设备控制表,将对应设备分配给请求进程;未找到则等待等待唤醒和分配。
+
+4. 到设备控制表中找出与其相连接的控制器的控制器控制表,根据状态字段判断是否忙碌,忙则等待;否则将该控制器分配给进程。
+
+5. 到该控制器的控制器控制表中找出与其相连接的通道的通道控制表,判断通道是否忙碌,忙则等待;否则将该通道分配给进程。
+
+6. 只有在设备、控制器和通道三者都分配成功时,这次的设备分配才算成功,然后便可启动设备进行数据传送。
+
+**17.何谓设备虚拟?实现设备虚拟时所依赖的关键技术是什么?**
+
+答:设备虚拟是指把独占设备经过某种技术处理改造成虚拟设备。可虚拟设备是指一台物理设备在采用虚拟技术后,可变成多台逻辑上的虚拟设备,则可虚拟设备是可共享的设备,将它同时分配给多个进程使用,并对这些访问该物理设备的先后次序进行控制。
+
+**18.试说明SPOOLing 系统的组成。**
+
+答:SPOOLing系统由输入井和输出井、输入缓冲区和输出缓冲区、输入进程 SPi 和输出进程 SPo 三部分组成。
+
+**19.在实现后台打印时,SPOOLing 系统应为请求I/O的进程提供哪些服务?**
+
+答:在实现后台打印时,SPOOLing 系统应为请求 I/O的进程提供以下服务:
+
+1. 由输出进程在输出井中申请一空闲盘块区,并将要打印的数据送入其中;
+
+2. 输出进程为用户进程申请空白用户打印表,填入打印要求,将该表挂到请求打印队列。
+
+3. 一旦打印机空闲,输出进程便从请求打印队列的队首取出一张请求打印表,根据表中要求将要打印的数据从输出井传送到内存缓冲区,再由打印机进行打印。
+
+**20.试说明设备驱动程序具有哪些特点。**
+
+答:设备驱动程序具有如下特点:
+
+1. 是请求 I/O 进程与设备控制器间的一个通信程序;
+
+2. 驱动程序与 I/O 设备的特性紧密相关;
+
+3. 驱动程序与 I/O 控制方式紧密相关;
+
+4. 驱动程序与硬件紧密相关,部分程序用汇编语言书写,基本部分往往固化在ROM中。
+
+**21.试说明设备驱动程序应具有哪些功能?**
+
+答:设备驱动程序的主要功能包括:
+
+1. 将接收到的抽象要求转为具体要求;
+
+2. 检查用户I/O请求合法性,了解I/O设备状态,传递有关参数,设置设备工作方式;
+
+3. 发出I/O命令,启动分配到的I/O设备,完成指定I/O操作;
+
+4. 及时响应由控制器或通道发来的中断请求,根据中断类型调用相应中断处理程序处理;
+
+5. 对于有通道的计算机,驱动程序还应该根据用户I/O请求自动构成通道程序。
+
+**22.设备中断处理程序通常需完成哪些工作?**
+
+答:设备中断处理程序通常需完成如下工作:
+
+1. 唤醒被阻塞的驱动程序进程;
+
+2. 保护被中断进程的CPU环境;
+
+3. 分析中断原因、转入相应的设备中断处理程序;
+
+4. 进行中断处理;
+
+5. 恢复被中断进程。
+
+**23.磁盘访问时间由哪几部分组成?每部分时间应如何计算?**
+
+答:磁盘访问时间由寻道时间Ts、旋转延迟时间Tr、传输时间Tt 三部分组成。
+
+1. Ts 是启动磁臂时间s 与磁头移动n条磁道的时间和,即Ts = m × n + s。
+
+2. Tr是指定扇区移动到磁头下面所经历的时间。硬盘15000r/min时Tr为2ms;软盘300或600r/min时Tr为50~100ms。
+
+3. Tt 是指数据从磁盘读出或向磁盘写入经历的时间。Tt的大小与每次读/写的字节数b和旋转速度有关:Tt = b/rN。
+
+**24.目前常用的磁盘调度算法有哪几种?每种算法优先考虑的问题是什么?**
+
+答:目前常用的磁盘调度算法有先来先服务、最短寻道时间优先及扫描等算法。
+
+1. 先来先服务算法优先考虑进程请求访问磁盘的先后次序;
+
+2. 最短寻道时间优先算法优先考虑要求访问的磁道与当前磁头所在磁道距离是否最近;
+
+3. 扫描算法考虑欲访问的磁道与当前磁道间的距离,更优先考虑磁头当前的移动方向。
+
+**25.为什么要引入磁盘高速缓冲?何谓磁盘高速缓冲?**
+
+答:目前磁盘的I/O速度远低于内存的访问速度,通常低上4-6个数量级。因此,磁盘I/O已成为计算机系统的瓶颈。为提高磁盘I/O的速度,便引入了磁盘高速缓冲。
+
+磁盘高速缓冲是指利用内存中的存储空间,暂存从磁盘中读出的一系列盘块中的信息。
+
+**26.在设计磁盘高速缓冲时,如何实现数据交付?**
+
+答:数据交付是指将磁盘高速缓存中的数据传给请求进程。当进程请求访问某个盘块中的数据时,由核心先查看磁盘高速缓冲,看其中是否存在所需盘块数据的拷贝。若有便直接从中提取数据交付给请求进程,避免了访盘操作,本次访问速度提高4-6个数量级;否则先从磁盘中将要访问的数据读入并交付给请求者进程,同时送高速缓存以便下次直接读取。
+
+**27.何谓提前读、延迟写和虚拟盘?**
+
+答:提前读是指在读当前盘块的同时,将下一个可能要访问的盘块数据读入缓冲区,以便需要时直接从缓冲区中读取,无需启动磁盘。延迟写是指在写盘块时,将对应缓冲区中的立即写数据暂时不立即写以备不久之后再被访问,只将它置上“延迟写”标志并挂到空闲缓冲队列的末尾。当移到空闲缓冲队首并被分配出去时,才写缓冲区中的数据。只要延迟写块仍在空闲缓冲队列中,任何要求访问都可直接从其中读出数据或将数据写入其中,而不必去访问磁盘。虚拟盘又称RAM盘,是利用内存空间仿真磁盘。其设备驱动程序可以接受所有标准的磁盘操作,但这些操作不是在磁盘上而是在内存中,因此速度更快。
+
+**28.廉价磁盘冗余阵列是如何提高对磁盘的访问速度和可靠性的?**
+
+答:廉价磁盘冗余阵列RAID是利用一台磁盘阵列控制器,统一管理和控制一组(几台到几十台)磁盘驱动器,组成高度可靠快速大容量的磁盘系统。操作系统将RAID中的一组物理磁盘驱动器看作一个单个的逻辑磁盘驱动器。用户数据和系统数据可分布在阵列的所有磁盘中,并采取并行传输方式,大大减少数据传输时间和提高了可靠性。
+
+## 第六章
+
+**1.何谓数据项、记录和文件?**
+
+1. 数据项分为基本数据项和组合数据项。基本数据项描述一个对象某种属性的字符集,具有数据名、数据类型及数据值三个特性。组合数据项由若干数据项构成。
+
+2. 记录是一组相关数据项的集合,用于描述一个对象某方面的属性。
+
+3. 文件是具有文件名的一组相关信息的集合。
+
+**2.文件系统的模型可分为三层,试说明其每一层所包含的基本内容。**
+
+第一层:对象及其属性说明(文件、目录、硬盘或磁带存储空间);
+
+第二层:对对象操纵和管理的软件集合(I/O控制层即设备驱动程序、基本文件系统即物理I/O层、基本I/O管理程序或文件组织模块层、逻辑文件系统层)
+
+第三层:文件系统接口(命令接口/图形化用户接口与程序接口)。
+
+**3.试说明用户可以对文件施加的主要操作有哪些?**
+
+答:用户通过文件系统提供的系统调用对文件实施操作。
+
+1. 基本文件操作:创建、删除、读、写、截断、设置读/写位置等;
+
+2. 文件打开和关闭操作:第一步通过检索文件目录找到指定文件属性及其在外存上位置;第二步对文件实施读写等相应操作。
+
+3. 其他文件操作:一是文件属性操作;二是目录操作;三是文件共享与文件系统操作的系统调用实现等。
+
+**4.何谓逻辑文件?何谓物理文件?**
+
+答:逻辑文件是物理文件中存储的数据的一种视图方式,不包含具体数据,仅包含物理文件中数据的索引。物理文件又称文件存储结构,是指文件在外存上的存储组织形式。
+
+**5.如何提高对变长记录顺序文件的检索速度?**
+
+答:基本方法是为变长记录顺序文件建立一张索引表,以主文件中每条记录的长度及指向对应记录的指针(即该记录在逻辑地址空间的首址)作为相应表项的内容。由于索引表本身是一个定长记录的顺序文件,若将其按记录键排序,则实现了对主文件方便快捷的直接存取。如果文件较大,应通过建立分组多级索引以进一步提高检索效率。
+
+**6.试说明对索引文件和索引顺序文件的检索方法。**
+
+1. 索引文件的检索,首先根据用户(程序)提供的关键字,利用折半查找法检索索引表,找到相应表项;再利用给出的指向记录指针值,访问对应记录。
+
+2. 索引顺序文件的检索,首先利用用户(程序)提供的关键字及查找方法,检索索引表,找到该记录在记录组中的第一条记录表项,得到第一个记录在主文件中的位置;再利用顺序查找法查找主文件,找到所要求的记录。
+
+**7.试从检索速度和存储费用两方面对索引文件和索引顺序文件进行比较。**
+
+答:索引文件的主文件每条记录配置一个索引项,存储开销N,检索到具有指定关键字的记录,平均查找N/2条记录。对于索引顺序文件,每个记录分组配置一个索引项,存储开销为*N*,检索到具有指定关键字的记录,平均需要查找*N* /2次。
+
+**8.试说明顺序文件的结构及其优点。**
+
+答:第一种是串结构:各记录之间的顺序与关键字无关。第二种是顺序结构:指文件中的所有记录按关键字(词)排列。可以按关键词长短排序或英文字母顺序排序。
+
+顺序文件的最佳应用场合是对诸记录进行批量存取时,存取效率最高;只有顺序文件才能存储在磁带上并有效工作。
+
+**9.在链接式文件中常用哪种链接方式?为什么?**
+
+答:链接方式分为隐式链接和显式链接两种形式。隐式链接是在文件目录的每个目录项中,都含有指向链接文件第一个盘块和最后一个盘块的指针。显式链接则把用于链接文件各物理块的指针,显式地存放在内存的一张链接表中。
+
+**10.在MS-DOS中有两个文件A 和B,A占用11、12、16和14四个盘块;B 占用13、18和20三个盘块。试画出在文件A和B中各盘块间的链接情况及FAT的情况。**
+
+答:如下图所示。
+
+**11.NTFS文件系统对文件采用什么样的物理结构?**
+
+答:在NTFS文件系统中,以簇作为磁盘空间分配和回收的基本单位。一个文件占若干个簇,一个簇只属于一个文件。
+
+**12.假定一个文件系统的组织方式与MS-DOS相似,在FAT中可有64K个指针,磁盘的盘块大小为512B,试问该文件系统能否指引一个512MB的磁盘?**
+
+解:512MB/512B=1M 个盘块,而每个盘块都应有一个指针来指示,所以应该有1M个指针,因此若有64K指针不能指引一个512MB的磁盘。
+
+**13.为了快速访问,又易于更新,当数据为以下形式时,应选用何种文件组织方式。⑴不经常更新,经常随机访问;⑵经常更新,经常按一定顺序访问;⑶经常更新,经常随机访问。**
+
+答:以上三种宜分别采用(1)顺序结构(2)索引顺序结构(3)索引结构的组织方式。
+
+**14.在UNIX中,如果一个盘块的大小为1KB,每个盘块号占4个字节,即每块可放256个地址。请转换下列文件的字节偏移量为物理地址。⑴9999; ⑵18000;⑶420000。**
+
+答:首先将逻辑文件的字节偏移量转换为逻辑块号和块内偏移量,就是将[字节偏移量]/[盘块大小],商为逻辑块号,余数是块内偏移量。在FCB中,第0-9个地址为直接地址,第10个为一次间接地址,第11个地址为二次间接地址,第12个地址为三次间接地址。再将文件的逻辑块号转换为物理块号。使用多重索引结构,在索引节点中根据逻辑块号通过直接索引或间接索引找到对应的物理块号。
+
+1. 9999/1024=9余783,则逻辑块号为9,直接索引第9个地址得到物理块号,块内偏移地址为783。
+
+2. 18000/1024=17余592,则逻辑块号为10<17<10+256,通过一次间接索引在第10个地址可得到物理块号,块内偏移地址为592。
+
+3. 420000/1024=410余160,则逻辑块号为10+256<410,通过二次间接索引在第11个地址可得到一次间址,再由此得到二次间址,再找到物理块号,其块内偏移地址160。
+
+**15.什么是索引文件?为什么要引入多级索引?**
+
+答:索引文件是指当记录为可变长度时,通常为之建立一张索引表,并为每个记录设置一个表项构成的文件。通常将索引非顺序文件简称为索引文件。索引是为了是用户的访问速度更快,多级索引结构可以有效的管理索引文件,可根据用户的访问情况多级处理。
+
+**16.试说明UNIX系统中所采用的混合索引分配方式。**
+
+答:混合索引分配方式是指将多种索引分配方式结合而成的分配方式。常见的是采用直接地址和一级索引联合的分配方式,或两级索引分配方式,甚至三级索引分配方式。在UNIX SystemⅤ和BSD UNIX 的索引结点中,都设置了13个地址项,即iaddr(0)~iaddr(12),把所有地址项分成直接地址和间接地址。
+
+**17.对目录管理的主要要求是什么?**
+
+答:实现按名存取、提高检索目录的速度、文件共享、允许文件重名。
+
+**18.采用单级目录能否满足对目录管理的主要要求?为什么?**
+
+答:不能。单级目录在整个文件系统中只建立一张目录表,每个文件占一个目录项,其中含文件名、文件扩展名、文件长度、文件类型、文件物理地址、状态位等其它文件属性。
+
+单级只能实现目录管理的基本功能,不能满足查找速度、允许重名和文件共享的要求。
+
+**19.目前广泛应用的目录结构有哪些?它有什么优点?**
+
+答:现代操作系统都采用多级目录结构。基本特点是查询速度快、层次结构清晰、文件管理和保护易于实现。
+
+**20.Hash 检索法有何优点?又有何局限性?**
+
+答:Hash检索法是系统把用户提供的文件名变换为文件目录的索引值,再利用该值查找目录,有效提高目录的检索速度,但Hash检索法局限于非通配符文件名。
+
+**21.在Hash检索法中,如何解决“冲突”问题?**
+
+答:在Hash法查找目录时,如果目录表中相应目录项为空,表示系统中无指定文件。如果文件名与指定文件名匹配,表示找到了目标文件,也就找到了文件的物理地址。如果目录表中找到的相应文件名不匹配,则发生了冲突,需要Hash转换形成新的索引值,返回第一步重新查找。
+
+**22.试说明在树型目录结构中线性检索法的检索过程,并给出相应的流程图。**
+
+答:在树型结构的目录中,当有两个或多个用户共享一个子目录或文件时,将共享文件或字母路连接到两个或多个用户目录中,方便找到该文件。此时目录结构不再是树形结构,而是个有向非循环图DGA。
+
+**23.有一计算机系统利用图6-33所示的位示图来管理空闲盘块。盘块的大小为1KB,现要为某文件分配量个盘块,试说明盘块的具体分配过程。**
+
+答:分配量个盘块的过程如下:
+
+1. 顺序扫描位示图,从中找到第一个值为0的二进制位,得到行号i=3,列号j=3。
+
+2. 将找到的二进制位转换成对应盘块号。盘块号为:b=(3-1)*16+3=35;
+
+3. 修改位示图,令map[3,3]=1,并将该盘块分配出去。
+
+类似地,可使用相同的方法找到第二个值为0的二进制位,得到行号i=4,列号j=7,其对应的盘块号为55,令map[i,j]=1,并将该盘块分配出去。
+
+**24.某操作系统磁盘文件空间共500块,若用字长为32位的位示图管理磁盘空间,试问:(1)位示图需要多少字?(2)第i字第j位对应的块号是多少?(3)给出申请/归还一块的工作流程。**
+
+(1)位示图需要的字数计算:INT(500/32)=16 个字。
+
+(2)块号b=(i-1)*32+j
+
+(3)申请的过程:顺序扫描位示图、找到空闲块并分配、修改位示图map[i,j]=1。
+
+归还的过程:找到回收盘块在位示图中的行和列,修改位示图map[i,j]=0。
+
+**25.对空闲磁盘空间的管理常采用哪几种分配方式?在UNIX系统中采用何种分配方式?**
+
+答:空闲表法、空闲链表法、位示图法、成组链接法。UNIX系统采用的是成组链接法
+
+**26.基于索引节点的文件共享方式有何优点?**
+
+答:优点是建立新的共享链接时,不改变文件拥有者关系,仅把索引结点共享计数器加1,系统可获悉了由多少个目录项指向该文件。缺点是拥有者不能删除自己的文件,否则会出错。
+
+**27.基于符号链的文件共享方式有何优点?**
+
+答:能够通过网络链接世界上 任何地方的计算机中的文件。
+
+**28.在一级系统容错技术中,包括哪些容错措施?什么是写后读校验?**
+
+答:一级系统容错技术包括双份目录、双份文件分配表及写后读校验等容错措施。
+
+写后读校验是每次从内存缓冲区向磁盘写入一个数据块后,又立即从磁盘上读出该数据块,并送至另一缓冲区中,再将该缓冲区内容与内存缓冲区中在写后仍保留的数据进行比较。若两者一致,才认为写入成功,继续写下一个盘块。否则重写。若重写后仍不一致,则认为盘块缺陷,便将应写入该盘块的数据,写入到热修复重定向区中。
+
+**29.在第二级系统容错技术中,包括哪些容错措施?画图说明之。**
+
+答:第二级容错技术包括磁盘镜像和磁盘双工两种容错措施。图示如下:
+
+**30.何谓事务?如何保证事务的原子性?**
+
+答:事务是用于访问和修改各种数据项的一个程序单位。要保证事务的原子性必须要求一个事务在对一批数据执行修改操作时,要么全部完成,用修改后的数据代替原来数据,要么一个也不改,保持原来数据的一致性。
+
+**31.引入检查点的目的是什么?引入检查点后又如何进行恢复处理?**
+
+答:引入检查点的目的是使对事务记录表中事务记录的清理工作经常化。恢复处理由恢复例程来实现。首先查找事务记录表,确定在最近检查点以前开始执行的最后的事务Ti。找到Ti后再返回搜索事务记录表,找到第一个检查点记录,从该检查点开始,返回搜索各个事务记录,利用redo和undo过程对他们进行相应的处理。
+
+**32.为何引入共享锁?如何用互斥锁或共享锁来实现事务的顺序性?**
+
+答:引入共享锁是为了提高运行效率。在给对象设置了互斥锁和共享锁的情况下,如果事务Ti要对Q执行读操作,只需获得Q的共享锁。如果对象Q已被互斥锁锁住,则Ti必须等待;否则便获得共享锁对Q执行读操作。如果Ti要对Q执行写操作,则Ti还要获得Q的互斥锁。若失败则等待;成功则获得互斥锁并对Q执行写操作。
+
+**33.当系统中有重复文件时,如何保证他们的一致性?**
+
+答:可以采用两种方法:一是对所有的重复文件进行同样的修改,二是用新修改的文件替换所有的重复文件。
+
+**34.如何检索盘块号的一致性?检查时可能出现哪几种情况?**
+
+答:为了保证盘块号的一致性,先将计数器表中的所有表项初始化为0,用N个空闲盘块号计数器组成的第一组计数器对从空闲盘块表中读出的盘块号计数,用N个数据盘块号计数器组成的第二组计数器对从文件分配表中读出的已分配给文件使用的盘快号计数。如果两组计数中的对应数据互补则数据一致,反之则发生错误。检查时可能出现的情况:
+
+1. 两组计数器中盘块K的计数值均为0,应在空闲盘块表中增加盘块号K;
+
+2. 空闲盘块号计数器中盘块K的计数值为2,应删除一个空闲盘块号K;
+
+3. 空闲盘块号计数器中盘块号K的计数值为0,而数据盘块号计数器中盘块号K的计数值大于1,则错误严重,存在数据丢失等事件,必须立即报告系统加以处理。
+
+## 第七章
+
+**1.操作系统包括哪几种类型的用户接口?它们分别适用于哪种情况?**
+
+答:操作系统包括四种类型的用户接口:命令接口(分为联机与脱机命令接口)、程序接口、图形化用户接口和网络用户接口。命令接口和图形化用户接口支持用户直接通过终端来使用计算机系统,程序接口提供给用户在编制程序时使用,网络用户接口是面向网络应用的接口。
+
+**2.联机命令接口由哪些部分构成?**
+
+答:联机命令接口由一组联机命令、终端处理程序和命令解释程序构成。
+
+**3.联机命令通常包含哪些类型?每种类型又包含哪些主要命令?**
+
+答:联机命令通常包含如下类型:
+
+1. 系统访问类,主要是注册命令login、password;
+
+2. 磁盘操作类,包括磁盘格式化format、软盘复制diskcopy、软盘比较diskcomp及备份backup等命令;
+
+3. 文件操作类,包括文件显示type、文件拷贝copy、文件比较comp、文件重命名rename、文件删除erase等命令;
+
+4. 目录操作类,包括子目录建立mkdir、目录显示dir、子目录删除rmdir、目录结构显示tree、当前目录改变chdir等命令;
+
+5. 其它命令,包括输入输出重定向>、<,管道联接|、过滤命令/,批命令.bat等。
+
+**4.什么是输入输出重定向?试举例说明。**
+
+答:命令的输入通常取自标准输入设备键盘,命令输出则送往标准输出设备显示终端。如果在命令中设置输出定向“>”,其后接文件或设备名,则命令的结果输出将送到指定文件或设备上;如果使用输入重定向“<”,则不从键盘而是从重定向符右边的指定文件或设备上取得输入信息。这就是输入输出的重定向。
+
+**5.何谓管道联接?试举例说明。**
+
+答:管道联接是指把第一个命令的输出作为第二个命令的输入,或把第二个命令的输出作为第三条命令的输入,以此类推,由两条以上的命令可形成一条管道。在MS-DOS和UNIX中,都用"|"作为管道符号。其一般格式为:command1 |command2 | …|commandn。
+
+**6.终端设备处理程序的主要作用是什么?它具有哪些功能?**
+
+答:主要用于实现人机交互,它具有以下功能:
+
+(1)接收用户从终端上键入的字符;(2)字符缓冲,用于暂存接收的字符;(3)回送显示;(4)屏幕编辑;(5)特殊字符处理。
+
+**7.命令解释程序的主要作用是什么?**
+
+答:主要作用是:在屏幕上给出提示符,请用户输入命令,读入并识别命令,转至相应命令处理程序入口地址,把控制权交给该处理程序执行,最后将处理结果或出错信息送屏幕显示。
+
+**8.试说明MS-DOS的命令处理程序COMMAND.COM的工作流程。**
+
+COMMAND.COM的工作流程如下:
+
+1. 系统通电或复位后,初始化程序对整个系统完成初始化工作,自动执行Autoexec.bat文件,然后把控制权交给暂存部分,给出提示符等待接收用户键入命令;
+
+2. 暂存部分读入键盘缓冲区中的命令,判别文件名、扩展名及驱动器名是否正确,若有错则出错返回,正确则查找和识别命令;
+
+3. 若为内部命令,暂存部分找到后便从对应表项中获得命令处理程序的入口地址并执行;若为外部指令,则建立命令行,执行系统调用exec装入其命令处理程序,得到对应基地址并执行;若键入命令非法,则出错返回;
+
+4. 命令完成后,控制权重新交给暂存部分给出提示符等待接收用户命令,转(2)。
+
+**9.为了将已存文件改名,应用什么UNIX 命令?**
+
+答:对已存文件改名的命令为mv,其格式为:*mv oldname newname*。
+
+**10.要想将工作目录移到目录树的某指定点上,应利用什么命令?**
+
+答:用命令“cd ..”或“cd .”将当前目录上移或转移,直到工作目录移到目录树的指定点。
+
+**11.如果希望把file1的内容附加到原有的文件file2的末尾,应用什么指令?**
+
+答: `cat file1 >> file4`
+
+**12.试比较mail和write命令的作用有何不同?**
+
+答: mail命令作为UNIX的多用户之间非交互式通信的工具。write命令是用户与当前系统中的其他用户直接进行联机通讯的工具。
+
+**13. 试比较一般的过程调用和系统调用?**
+
+答: 系统调用本质上是过程调用的一种特殊形式,与一般过程调用有差别:
+
+1. 运行状态不同。一般过程调用的调用过程和被调用过程均为用户程序,或者均为系统程序,运行在同一系统状态(用户态或系统态);系统调用的调用过程是用户态下的用户程序,被调用过程是系统态下的系统程序。
+
+2. 软中断进入机制。一般的过程调用可直接由调用过程转向被调用过程;而系统调用不允许由调用过程直接转向被调用过程,一般通过软中断机制,先进入操作系统内核,经内核分析后,才能转向相应命令处理程序。
+
+3. 返回及重新调度。一般过程调用在被调用结束后,返回调用点继续执行;系统调用被调用完后,要对系统中所有运行进程重新调度。只有当调用进程仍具有最高优先权才返回调用过程继续执行。
+
+4. 嵌套调用。一般过程和系统调用都允许嵌套调用,注意系统过程嵌套而非用户过程。
+
+**14.什么是系统调用?它都有哪些类型?**
+
+答:系统调用是指在操作系统内核设置的一组用于实现各种系统功能的子程序或过程,并提供给用户程序调用。主要类型包括:
+
+1. 进程控制类。用于进程创建、终止、等待、替换、进程数据段大小改变及进程标识符或指定进程属性获得等;
+
+2. 文件操纵类。用于文件创建、打开、关闭、读/写及文件读写指针移动和属性修改,目录创建及索引结点建立等;
+
+3. 进程通信类,用于实现通信机制如消息传递、共享存储区及信息量集机制等;
+
+4. 信息维护类,用于实现日期、时间及系统相关信息设置和获得。
+
+**15.如何设置系统调用所需的参数?**
+
+答:设置系统调用参数包括两种方式:
+
+1. 直接将参数送入相应的寄存器中。问题是寄存器有限,限制了设置参数的数目。
+
+2. 参数表方式。将系统调用所需参数,放入参数表中,再将该表指针放在寄存器中。
+
+**16.试说明系统调用的处理步骤。**
+
+1. 设置系统调用号和参数。
+
+2. 对系统调用命令的一般性处理。如保护CPU现场,PSW、PC、系统调用号、用户栈指针及通用寄存器入栈,保存用户定义参数等。UNIX中执行CHMK命令将参数表中的参数传到User结构的U.U-arg()中;MS-DOS执行INT21软中断。
+
+3. 根据系统调用入口表及具体系统调用命令转至对应命令处理程序具体处理。
+
+**17.为什么在访问文件前,要用open系统调用先打开该文件?**
+
+答: 系统将在用户与该文件之间建立一条快捷通路。在文件被打开后,系统将给用户返回一个该文件的句柄或描述符。
+
+**18.在UNIX系统中是否设置了专门用来删除文件的系统调用?为什么?**
+
+答: 没有。当用户不再使用此文件时,利用系统调用unlink断开连接,做i.link减1操作。当i.link减1结果为0,表示此文件不再被用户需要,该文件将从文件系统中删除。
+
+**19.在IPC软件包中包含哪几种通信机制?在每种通信机制中设置了那些系统调用?**
+
+答: IPC中提供了三种通信机制:
+
+1. 消息机制。存在msgget,msgsend,msgrcv系统调用。
+
+2. 共享存储器机制。存在shmget,shmid,shmdt系统调用。
+
+3. 信号量机制。无系统调用。
+
+**20. trap.S是什么程序?它完成哪些主要功能?**
+
+答:UNIX系统V内核中的trap.S文件,是中断和陷入总控程序。用于中断和陷入的一般性处理,由汇编语言编写。trap.S中包含了绝大部分的中断和陷入向量的入口地址,每当系统发生中断和陷入时,通常都是直接进入trap.S程序。
+
+**21.在UNIX系统内,被保护的CPU环境中包含哪些数据项?**
+
+答:当用户程序处在用户态且执行CHMK (CHange Mode toKernel)之前,应在用户空间提供系统调用所需参数表,并将参数表地址送入R0寄存器。执行CHMK命令后,处理机转为核心态,由硬件自动将处理机状态长字(PSL)、PC和代码操作数(code)压入用户核心栈,从中断和陷入向量表中取出trap.S入口地址,转入trap.S中执行。
+
+trap.S程序执行后,将陷入类型type和用户栈指针usp压入用户核心栈,将被中断进程的CPU环境中的一系列寄存器如R0~R11的部分或全部压栈。哪些寄存器内容压栈,取决于特定寄存器的屏蔽码,屏蔽码每一位都与R0~R11中的寄存器相对应。当某一位置1时,表示对应寄存器内容压栈。
+
+**22. trap.C 是什么程序?它将完成哪些处理?**
+
+答:trap.C 程序是处理各种陷入情况的C语言文件,共处理12种陷入后的公共问题。包括:确定系统调用号、实现参数传递、转入相应系统调用处理子程序。在由系统调用子程序返回到trap.C后,重新计算进程的优先级,对收到的信号进行处理等。
+
+**23.为方便转入系统调用处理程序,在UNIX系统中配置了什么样的数据结构?**
+
+答:在UNIX系统中配置了系统调用定义表sysent[],在表的每个结构中包含三个元素,一是相应系统调用所需参数的个数;二是系统调用经寄存器传送的参数个数;三是相应系统调用处理子程序的入口地址。系统中设置了该表之后,可根据系统调用号i从系统调用定义表中找出相应表目,按表目中的入口地址转入相应处理子程序,完成系统调用的特定功能。执行完后,返回中断和陷入总控程序中的trap.C程序中,返回断点前的公共处理部分。
+
+## 第八章网络操作系统
+
+**1.按网络拓扑结构可以把计算机网络分为哪几类?试画出它们的网络拓扑图。**
+
+答:计算机网络可分为星形、环形、总线形、树形和网状形网络。它们的网络拓扑图如下:
+
+**2.试说明分组交换网的组成。**
+
+答:由分组交换机、网路管理中心、远程集中器、分组装拆设备以及传输设备等组成。
+
+**3.何谓帧交换方式及信元交换方式?**
+
+答:帧交换方式是在传统分组交换的基础上发展起来的,传输基本单位是帧,长度可变,采用“存储转发”方式,即帧交换器每接到一个新帧时,都将该帧送帧缓冲区排队,按照该帧中的目标地址,将该帧转发给相应路径的下一个帧交换器。信元交换方式是改进了的帧中继交换方式。当源帧交换器收到用户设备发来的帧,便分割为多个定长信元,在整个帧中继器网络中传输和交换时,都以信元为基本单位,到达目标帧交换器后,被重组为帧。
+
+**4.局域网可分为基本型和快速型两大类,每一类中包括哪几种局域网?**
+
+答:基本型局域网有:(1)以太网(2)令牌环网。快速局域网有:(1)FDDI光纤环网(2)快速以太网100 BASE-T。
+
+**5.为实现同构LAN网络互连,应采用什么样的网络互连设备?应具有哪些功能?**
+
+答:同构LAN网络互连设备与功能:
+
+1. 网桥。功能:帧的发送和接受、缓冲处理、协议转换。
+
+2. 路由器。功能:拆包和打包、路由选择、协议转换、分段和重组
+
+**6.为实现异构型网络互连,应采用什么样的网络互联设备?它又应具有哪些功能?**
+
+答:采用网关。实现异构LAN互连、LAN与WAN互连、WAN互连、LAN与主机互连。
+
+**7.网络层向传输层提供了哪两类数据传输服务?试对它们做简要的说明。**
+
+1. 数据包服务。发方网络层从传输层接收报文,为它配上完整的目标地址,作为独立信息单位传送出去。数据包每经过一个中继节点都根据当时当地情况,按一定算法选择一条最佳传输路径转发出去。采用数据包服务的收、发双发无需建立连接。
+
+2. 虚电路服务。通信前由源主机发送呼叫报文分组,包含源和目标主机的全网地址。目标主机同意通信,便由网络层在双方间建立一条虚电路。在以后通信中只需填上虚电路的逻辑信道号;通信结束拆除该虚电路。
+
+**8.传输层所起的桥梁作用具体表现在哪几方面?**
+
+1. 传输出错率和建立连接的失败率。
+
+2. 数据传输速率、吞吐量和传输时延。
+
+3. 分段和组段功能。
+
+**9.TCP/IP模型中包含了哪几个层次?简要说明每个层次的主要功能。**
+
+答:TCP/IP模型中包含4个层次。
+
+1. 应用层。对应于OSI高层,为用户提供需要的服务。如FTP、Telnet、DNS等。
+
+2. 传输层。对应于OSI传输层,为应用层实体提供端到端的通信功能。定义了面向连接的TCP和无连接的用户数据报协议UDP这两个主要协议。
+
+3. 网络互联层。对应于OSI网络层,解决主机到主机的通信问题。有网际协议IP、地址解析协议ARP、互联网组管理协议IGMP和互联网控制报文协议ICMP四个主要协议。
+
+4. 网络访问层。对应OSI的物理层和数据链路层。
+
+**10.网络互联层IP协议的主要作用是什么?为什么在有了IP协议之后还要配置TCP协议?**
+
+1. IP协议主要用于异构网络间的相互连接和路由选择。IP 提供的是不可靠、面向无连接的数据报传递服务。
+
+2. TCP协议提供面向连接、可靠的端端通信机制。TCP比IP可以确保数据传输的可靠性,即使网络层出错,TCP仍能正确控制建立连接、数据传输和连接释放。
+
+**11.试说明在介质访问控制MAC子层中,IEEE 802.2、IEEE802.3、IEEE 802.3u、IEEE 802.2z、IEEE 802.5、IEEE802.6都是些什么标准?**
+
+1. IEEE 802.2是逻辑链路控制的标准。IEEE 802.3是以太网的标准。
+
+2. IEEE 802.3u是以太网的标准。IEEE 802.2z是以太网的标准。
+
+3. IEEE 802.5是令牌环的标准。IEEE 802.6是城域网的标准。
+
+**12.何谓网络体系结构?OSI/RM由哪几部分组成?**
+
+答:网络体系结构是指通信系统的整体设计,为网络硬件、软件、协议、存取控制和拓扑提供标准。OSI/RM 从低到高分七层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
+
+**13.什么是网络协议?扼要说明其所含的三要素。**
+
+答:网络协议是为计算机网络中进行数据交换而建立的规则、标准或约定的集合。计算机网络协议主要由语义、语法和交换规则三部分即协议三要素组成。语义:规定通信双方彼此讲什么,确定协议元素类型,如规定通信双方发什么控制信息,执行的动作和返回的应答。语法:规定通信双方彼此如何讲,确定协议元素格式,如数据和控制信息的格式。交换规则:规定信息交流的次序。
+
+**14.ISO将OSI/RM分成几层?各层的主要用途是什么?**
+
+答:OSI/RM分7层。各层的主要用途是:
+
+物理层:规定了网络设备间物理连接标准,在网络设备间透明地传输比特流。
+
+数据链路层:提供相邻节点间可靠的数据传输功能。
+
+网络层:在通信子网中进行路由选择和通信控制。
+
+传输层:提供两个端系统间的可靠通信。
+
+会话层:建立和控制两个应用实体间的会话过程。
+
+表示层:提供统一的网络数据表示。
+
+应用层:提供网络用户间的分布式应用环境(普通用户)和应用开发环境(网络程序员)。
+
+**15.客户/服务器模式得以广泛流行的主要因素是什么?**
+
+1. 模块化与应用的分布特性
+
+2. 充分利用资源,提高网络效率
+
+3. 便与系统维护,扩充性强
+
+4. 并发特性
+
+**16..试说明客户与服务器之间的交互情况。**
+
+答:C/S 模式的两层结构系统是:第一层在客户机系统上结合表示与业务逻辑;第二层通过网络结合了数据库服务器。C/S 模式主要由客户应用程序、服务器管理程序和中间件三部分组成。
+
+**17.两层C/S模式有哪些局限性?如何解决?**
+
+1. 不能适应应用不断增多的情况。
+
+2. 需要在客户机与服务器上安装特定的网络软件,实现C/S间的互用性。
+
+3. 客户机直接与服务器交互。
+
+解决办法:设法使C与提供数据等服务的S无关,在C/S间增设中间实体。
+
+**18.为什么在大型信息系统和Internet环境下,应采用三层客户/服务器模式?**
+
+答:因为Internet发展极为迅速,三层客户/服务器模式更适合发展。把客户机作为Web浏览器,从而形成了Web浏览器、Web服务器和数据库服务器三层的C/S 模式。
+
+**19.试比较两层和三层的**C/S**模式。**
+
+答:三层与两层模式相比的优点:(1)增加了系统的灵活性和可扩展性。(2)简化了客户机,降低了系统费用。(3)使客户机安装、配置和维护更为方便。
+
+三层的缺点:(1)软件开发难度大,开发周期长。(2)访问效率低。
+
+**20.现代计算机网络有哪些主要功能。**
+
+答:计算机网络的主要功能是数据通信和资源共享、系统容错、网络管理、应用互操作功能。
+
+**21.试说明在层次式结构的网络中进行数据通信时,信息的流动过程。**
+
+答:请求信息从客户机到应用服务器,再到数据服务器,然后数据服务器根据要求向应用服务器传送信息,再由应用服务器找到客户机。
+
+**22.为实现数据通信,计算机网络应有哪些具体功能?**
+
+答:连接的建立和拆除、报文的分解和组装、传输控制、流量控制、差错检测与纠正。
+
+**23.试说明当前实现文件和数据共享的两种主要方式。**
+
+答:以虚拟软盘方式和以文件服务方式实现的数据共享方式。
+
+**24.网络管理的主要目标是什么?**
+
+答:A.增强网络的可用性。 B.提高网络运行质量。 C.提高网络资源利用率。D.保障网络的安全性 E.提高网络和社会经济效益。
+
+**25.网络管理包括哪几方面的具体功能?**
+
+答:配置管理、故障管理、性能管理、安全管理、计费管理。
+
+**26.何谓信息“互通性”和信息“互用性”?**
+
+答:信息的互通性是指在不同网络结点间实现通信。目前主要利用TCP/IP实现信息互通。信息的互用性是指在不同网络中的站点间实现信息的互用,即一个网络中的用户能访问另一个网络文件系统或数据库系统中的文件或数据。
+
+**27.何谓电子邮件?它可分为哪几种类型?**
+
+答:电子邮件E-mail,标志@,又称电子信箱、电子邮政,是用电子手段提供信息交换的通信方式。电子邮件服务器分为两种类型,MIME 协议和SMTP协议。现代E-mail中可包含多种不同类型的文件,如文本、图像、音频和视频信息等。
+
+**28.文件传输的复杂性表现在哪几方面?如何解决?**
+
+答:异构网络下的文件传输,需要在Internet中建立了统一的文件传输协议FTP。
+
+(1)内部用户FTP。只允许在文件服务器上拥有账户的用户使用FTP服务。
+
+(2)匿名FTP。在Internet 上实现资源共享的重要手段,允许非注册用户拷贝文件。
+
+**29.试比较电子邮件服务和文件传输服务。**
+
+答:电子邮件服务借助于E-mail设施与世界上所有国家和地区的网络用户通信。文件传输服务是在Internet 中建立统一的文件传输协议FTP,实现用户在不同主机间的文件拷贝功能。
+
+**30.网络环境下的目录服务有何特点?**
+
+答:规模小的局域网不需要提供目录服务,对于大型企业网必须对网络管理员和用户提供目录服务,发挥网络的应有作用。目录服务还应能对每台物理设备提供的网络服务进行管理。对服务器提供的网络服务可以是文件/打印服务、数据库服务等。
+
+**31. 目录服务包括哪些主要功能?**
+
+1. 用户管理。保证核准用户能方便地访问各种网络服务,禁止非法用户访问。
+
+2. 分区和复制。将庞大目录库分成若干个分区,并分别复制到多台服务器,使每个分区被复制的位置尽量靠近最常使用这些对象的用户,有的目录服务还允许一台服务器上存放多个不同分区的拷贝。
+
+3. 创建扩充和继承功能。创建是在目录中创建新的对象,并设置属性。扩充指对原有目录服务功能的扩充。继承是指目录对象继承其他对象的属性和权力的能力。
+
+4. 多平台支持功能。由于目录服务存在着管理对象的差异,要求具有跨越平台能力。
+
+**32. Internet 具有哪些特征?**
+
+答:(1)广域性 (2)广泛性 (3)高速性(4)综合性
+
+**33.何谓WWW?它与一般的信息检索工具有何不同?**
+
+答:WWW(Word Wide Web)称为万维网或Web,是当前最为流行的信息服务类型。它与一般信息检索工具不同表现在:一般检索工具每次只能从一台主机上查找需要的文件,且文件数据类型单一;而Web检索可以一次从多台主机中查找需要的数据,允许类型各异,并将这些数据形成一份文件。
+
+**34.何谓BBS?它何以会受到广大网络用户的欢迎?**
+
+答:BBS(Bulletin BoardSystem)即电子公告板。BBS用户已经扩展到各行各业,BBS可以交换各种文件。通过BBS系统可随时取得国际最新软件及信息,可以和别人讨论计算机软件、硬件、Internet、多媒体、程序设计以及医学等各种有趣话题,可以利用BBS刊登征友、廉价转让及公司产品等启事。只要拥有1台计算机和上网设备就能立刻进入“超时代”BBS领域,享用它无比的威力!因此BBS 受到了广大网络用户的欢迎。
+
+**35.什么是域名服务?Internet的域名是由几段构成的?**
+
+答:域名是Internet 网络上的一个服务器或一个网络系统的名字。域名的形式是以若干个英文字母和数字组成,由"."分隔成几部分,如cctv.com就是一个域名。一个完整的域名由两个或两个以上词段组成,部分之间用英文句号"."分隔,最后一个"."的右边部分称为顶级域名(TLD)或一级域名,最后一个"."的左边部分称为二级域名(SLD),二级域名的左边部分称为三级域名,以此类推,每一级的域名控制它下一级域名的分配。
+
+**36.什么是域名解析?最基本的一种域名解析方式是如何实现的?**
+
+答:域名解析是将域名重新转换为对应IP地址的过程。一个域名只对应一个IP地址,多个域名可以同时解析到一个IP地址。域名解析需要由专门的域名解析服务器DNS完成。域名解析的过程:当应用过程需要将一个主机域名映射为IP地址时,就调用域名解析函数将待转换的域名放在DNS请求中,以UDP报文方式发给本地域名服务器。查到域名后将对应IP地址放在应答报文中返回。若域名服务器不能回答该请求,则此域名服务器向根域名服务器发出请求解析,找到下面的所有二级域名服务器,以此类推,直到查询到所请求的域名并赋IP值返回。
+
+**37.为能支持Internet所提供的服务,在操作系统中应配置哪些软件?**
+
+答:应配置WEB浏览器,如IE、firefox、Chrome等,特殊的服务可以根据需要安装对应的软件。
+
+**38.何谓浏览器/服务器模式?浏览器和服务器的基本功能是什么?**
+
+答:浏览器/服务器模式即B/S结构或Browser/Server结构。只安装维护一个服务器Server,客户端采用浏览器Browse 软件。利用成熟的WWW技术,结合多种Script语言(VBScript、JavaScript…)和ActiveX技术,是全新的软件系统构造技术。在B/S体系结构系统中,浏览器向分布在网络上的许多服务器发出请求,服务器对浏览器的请求进行处理,将用户所需信息返回到浏览器。而数据请求、加工、结果返回及动态网页生成、数据库访问和应用程序执行等工作全部由Web Server完成。随着Windows将浏览器技术植入操作系统内部,这种结构已成为当今应用软件的首选体系结构。B/S 结构的主要特点是分布性广、维护方便、开发简单、共享性强、总体成本低。但数据安全性、服务器要求高、数据传输慢、软件个性化特点明显降低,难以实现传统模式下的特殊功能要求。浏览器是指可以显示网页服务器或者文件系统的HTML文件内容,并让用户与这些文件交互的一种软件。服务器是网络上为客户端计算机提供各种服务的高可用性计算机。
+
+## 第九章系统安全性
+
+**1.系统安全的复杂性表现在哪几个方面?**
+
+1. 多面性:大规模系统存在多个风险点,每点都包括物理、逻辑及管理三方面安全。
+
+2. 动态性:信息技术不断发展和攻击手段层出不穷,系统安全问题呈现出动态性。
+
+3. 层次性:系统安全涉及多方面且相当复杂的问题,需要采用系统工程方法解决。
+
+4. 适度性:根据实际需要提供适度安全目标加以实现。
+
+**2.对系统安全性的威胁有哪几种类型?**
+
+答:假冒身份、数据截获、拒绝服务、修改伪造信息、否认操作、中断传输、通信量分析。
+
+**3.攻击者可通过哪些途径对软件和数据进行威胁?**
+
+答:数据截获,修改信息,伪造信息,中断传输
+
+**4.可信任计算机系统评价标准将计算机系统的安全度分为哪几个等级?**
+
+答:该标准将计算机系统安全程度分为8级,有D1(安全度最低级)、C1(自由安全保护级)、C2(受控存取控制级)、B1、B2、B3、A1、A2。
+
+**5.何谓对称加密算法和非对称加密算法?**
+
+答:对称加密也叫私钥加密,是指加密和解密使用相同密钥的加密算法。加密密钥能够从解密密钥中推算出来,解密密钥也能够从加密密钥中推算出来。在大多数对称算法中,加密和解密的密钥相同,也称为保密密钥算法或单密钥算法。非对称加密算法需要两个密钥:公钥(publickey)和私钥(privatekey)。公钥与私钥配对,如果用公钥加密数据,只有用对应的私钥才能解密。
+
+**6.什么是易位法和置换算法?试举例说明置换算法。**
+
+答:易位法是指按一定规则,重新安排明文中的比特或字符顺序形成密文,而字符本身保持不变。置换法是按照一定规则,用一个字符去置换另一个字符形成密文。如:How are you?的每个字符用后面的字母代替就是Ipx bsf zpv?
+
+**7.试说明DES加密的处理过程。**
+
+答:分为四个阶段:
+
+第一阶段,将明文分出64位明文段,并做初始易位得到X0,左移32位,记为L0,右移32位,记为R0。
+
+第二阶段,对X0进行16次迭代,每一次用56位加密密钥Ki。
+
+第三阶段,把经过16次迭代处理的结果的左32位与右32位互换位置。
+
+第四阶段,进行初始易位的逆变换。
+
+**8.试说明非对称加密的主要特点。**
+
+答:非对称加密算法复杂、安全性依赖于算法与密钥,加密解密速度慢。对称密码体制只有密钥,安全性就是密钥的安全性,而非对称加密有公钥和私钥,安全性更强。
+
+**9.试说明保密数据签名的加密和解密方式。**
+
+1. 发送者A可用自己的私用密钥Kda对明文P进行加密,得到密文DKda(P)。
+
+2. A再用B的公钥Keb对DKda(P)加密,得到EKeb(DKda(P))后送B。
+
+3. B收到后,先用私钥Kdb解密,得到DKda(EKeb(DKda(P)))=DKda(P)。
+
+4. B再用A的公钥Kea 对DKda(P)解密,得到EKeb(DKda(P))=P。
+
+**10.数字证明书的作用是什么?用一例来说明数字证明书的申请、发放和使用过程。**
+
+答:数字证明书又称公钥证明书,用于证明通信请求者的身份。数字证明书的申请、发放和使用过程如下:
+
+1. 用户A先向CA申请数字证明书,A应提供身份证明和希望使用的公钥A。
+
+2. CA收到A发来的申请报告后,若接受申请,便发给A一份数字证明书,其中包括公钥A和CA发证者的签名等信息,并对所有信息利用CA私钥加密(即对CA进行数字签名)。
+
+3. 用户A在向B发送信息时,由A用私钥对报文加密(数字签名),连同证明书发给B。
+
+4. 为能对收到的数字证明书解密,用户B须向CA申请获得CA的公钥B。CA 收到用户B的申请后,可决定将公钥B发给用户B。
+
+5. 用户B利用CA公钥B对数字证明书解密,确认该数字证明书系原件,并从数字证明书中获得公钥A,并且确认该公钥A系用户A的密钥。
+
+6. 用户B再利用公钥A对用户A发来的加密报文解密,得到用发来报文的真实明文。
+
+**11.何谓链路加密?其主要特点是什么?**
+
+答:链路加密是对网络相邻节点间的通信线路上传输的数据的加密过程。特点是:
+
+1. 相邻节点间的物理信道上传输的报文是密文,在所有中间节点上的报文则是明文。
+
+2. 对不同的链路分别采用不同的加密密钥。
+
+**12.何谓端-端加密?其主要特点是什么?**
+
+答:端-端加密是在源主机或前端机FEP高层(从传输层到应用层)对传输数据进行的加密。特点:
+
+1. 整个网络传输过程中的报文正文都是密文,信息到达目标主机后才译成明文。
+
+2. 不能对报头中的控制信息加密,否则中间结点无法得知目标地址和控制信息。
+
+**13.可利用哪几种方式来确定用户身份的真实性?**
+
+答:(1)口令密码组合;(2)物理标志(3)生物标志 (4)公开密钥
+
+**14.在基于口令机制的身份认证技术中,通常应满足哪些要求?**
+
+答:口令长度适中、自动断开连接、隐蔽回送显示、记录和报告。
+
+**15.基于物理标志的认证技术又可细分为哪几种?**
+
+答:主要有基于磁卡或IC卡的两种认证技术。
+
+**16.智能卡可分为哪几种类型?这些是否都可用于基于用户持有物的认证技术中?**
+
+答:智能卡分为存储器卡、微处理器卡和密码卡等类型。存储器卡没有安全功能,不能用于基于用户持有物的认证;微处理器卡和密码卡采用了加密措施,可以用于基于用户持有物的认证。
+
+**17.被选用的人的生理标志应具有哪几个条件?请列举几种常用的生理标志。**
+
+答:被选用的生理标志应具有三个基本条件,即足够的可变性、稳定性好、不易伪装。常用的生理标志是指纹、视网膜组织、声音、手指长度等。
+
+**18.对生物识别系统的要求有哪些?一个生物识别系统通常是有哪几部分组成的?**
+
+答:对生物识别系统的要求有:性能满足要求(抗欺骗和防伪防攻击)、能被用户接受、系统成本适当。一个生物识别系统通常由注册和识别两部分组成。注册部分配有一张用户注册表,识别部分要对用户进行身份认证和生物特征识别。
+
+**19.试详细说明SSL所提供的安全服务。**
+
+答:SSL称为安全套接层协议,用于提供Internet上的信息保密,身份认证服务,目前SSL已成为利用公开密钥进行身份认证的工业标准。SSL 提供的安全服务有:申请数字证书(服务器申请数字证书、客户申请数字证书)和SSL握手协议(身份认证、协商加密算法和协商加密密钥)。
+
+**20.什么是保护域?进程与保护域之间存在着什么动态联系?**
+
+答:保护域是进程对一组对象访问权的集合,规定了进程能访问对象和执行的操作。进程与保护域之间的动态联系是指进程的可用资源集在个生命周期中是变化的;进程运行在不同的阶段可以根据需要从一个保护域切换到另一个保护域。
+
+**21.试举例说明具有域切换权的访问控制矩阵。**
+
+答:在访问矩阵中增加几个对象,分别作为访问矩阵中的几个域,当且仅当switch包含在access(i,j)时,才允许进程从域i切换到域j。例如在下图中,域D1和D2对应的项目中有S,故允许域D1中的进程切换到域D2中,在域D2和D3中也有S,表示D2域中进行的进程可切换到域D3中,但不允许该进程再从域D3返回到域D1。
+
+**22.如何利用拷贝权来扩散某种访问权?**
+
+答:如果域i具有对象j的某访问权acess(i,j)的拷贝权,则运行在域i的进程可将其访问权acess(i,j)扩展到访问矩阵同一列中的其它域,即为运行在其它域的进程也赋予关于同一对象的同样访问(acess(i,j))。
+
+**23.如何利用拥有权来增删某种访问权?**
+
+答:如果域i具有关于对象j的所有权,则运行在域i的进程可以增删在j列的任何项中的任何访问权。或该进程可以增删在任何其它域中运行的进程关于对象j的任何访问权。
+
+**24.增加控制权的主要目的是什么?试举例说明控制权的应用。**
+
+答:控制权用于改变某个域中运行进程关于不同对象的访问权。若某域访问权access(i,j)中含有控制权C,则运行在Di域中的进程能改变运行在Qj域中的任何进程关于任何对象的任何访问权。
+
+**25.什么是访问控制表?什么是访问权限表?**
+
+答:访问控制表是指对访问矩阵按列划分,为每列建立一张访问控制表ACL,由有序对(域,权集)组成,用来保证系统安全性的一种手段。访问权限表是指对访问矩阵按行划分,由每行构成一张访问权限表。
+
+**26.系统如何利用访问控制表和访问权限表来实现对文件的保护?**
+
+答:当进程第一次试图访问一个对象时,必须先检查访问控制表,查看是否有权访问该对象。如果无则拒绝访问,并构成一个例外异常事件;否则便允许访问,并为之建立访问权限,以便快速验证其访问的合法性。当进程不再访问该对象时便撤销该访问权限。
+
+**27.什么是病毒?它有什么样的危害?**
+
+答:病毒是编制或者在计算机程序中插入的破坏计算机功能或数据,影响计算机系统使用并且能够自我复制的一组计算机计算机指令或程序代码。计算机病毒的危害:占用系统空间、占用处理机时间、破坏文件、使机器运行异常。
+
+**28. 计算机病毒的特征是什么?它与一般的程序有何区别?**
+
+答:计算机病毒的特征是寄生性、传染性、隐蔽性和破坏性。它与一般程序的区别是:病毒程序通常不是独立的程序,具有自我复制和迅速传播的传染性,想方设法隐藏自身,存在的基本目标就是破坏性。
+
+**29.什么是文件型病毒?试说明文件型病毒对文件的感染方式。**
+
+答:文件型病毒是指采用寄生方式附着在正常程序里,病毒发作时原来程序仍能正常运行,以致用户不能及时发现而长期潜伏下来的病毒。文件型病毒对文件的感染方式是主动攻击和执行时感染的方式。
+
+**30.病毒设计者采取了哪几种隐藏方式来让病毒逃避检测?**
+
+1. 隐藏于目录和注册表空间。
+
+2. 隐藏于程序的页内零头里。
+
+3. 更改用于磁盘分配的数据结构。
+
+4. 更改坏扇区列表。
+
+**31.用户可采用哪些方法来预防病毒?**
+
+1. 定期在外存备份重要软件和数据
+
+2. 使用安全性高的操作系统
+
+3. 使用正版软件
+
+4. 使用高性能反病毒软件
+
+5. 不轻易打开来历不明的电子邮件
+
+6. 定期检查外存并清除病毒
+
+**32.试说明基于病毒数据库的病毒检测方法。**
+
+答:(1)建立病毒数据库 (2)扫描硬盘上的可执行文件
+
+## 第十章
+
+**1.UNIX系统具有哪些特征?**
+
+答:开放性、多用户多任务环境、功能强大高效、丰富网络功能、支持多处理器。
+
+**2.试说明UNIX系统的内核结构。**
+
+答:UNIX内核结构分四层:最底层是硬件,次底层是OS 核心,第二层是OS与用户接口shell及编译程序等,最高层是应用程序。
+
+**3.UNIX系统中的PCB含哪几部分?用图说明各部分之间的关系。**
+
+答:UNIX系统中的PCB含进程表项、U区、系统区表、进程区表。
+
+**4.进程映像含哪几部分?其中系统级上、下文动态部分的作用是什么?**
+
+答:进程映像含用户上下文、寄存器上下文、系统级上下文。系统级上下文动态部分的作用是当因中断或系统调用进入核心状态时,核心把一个寄存器上下文压入核心栈,退出系统调用时,核心又弹出寄存器上下文,在上下文切换时,核心将压入老进程的上下文,弹出新进程的上下文。
+
+**5.在UNIX系统中用于进程控制的主要系统调用有哪些?它们各自的主要功能是什么?**
+
+答:用于进程控制的主要系统调用有:
+
+1. fork系统调用:用于创建新进程
+
+2. exit系统调用:实现进程自我终止
+
+3. exec系统调用:改变进程原有代码
+
+4. wait系统调用:将调用进程挂起并等待子进程终止
+
+**6.为创建一个新进程,须做哪些工作?**
+
+答:为新进程分配一个进程表项和进程标志符;检查同时运行的进程数目;拷贝进程表项中的数据;子进程继承父进程的所有文件;为子进程创建进程上下文;子进程执行。
+
+**7.为何要采取进程自我终止方式?如何实现exit?**
+
+答:为了及时回收进程占用的资源,在进程任务完成后应尽快撤销。Unix内核用exit实现进程的自我终止。父进程在创建子进程时,应在子进程末尾安排exit使子进程能自我终止。实现exit的具体操作是:关闭软中断、回收资源、写记账信息和置进程为僵死状态。
+
+**8.在UNIX系统中采用了何种调度算法?如何确定进程的优先数?**
+
+答:UNIX 系统采用动态优先数轮转的进程调度算法。优先数确定公式:优先数 =(最近使用CPU的时间/2)+ 基本用户优先数
+
+**9.在进入sleep过程后,内核应做哪些处理?**
+
+答:进入sleep过程后,核心首先保存进入睡眠时的处理机运行级,提高处理机的运行优先级屏蔽所有中断,将该进程置为睡眠状态,将睡眠地址保存在进程表项中,将该进程放入睡眠队列。如果进程的睡眠不可中断,在进程上下文切换后,进程便安稳睡眠。当进程被唤醒并被调度执行,将恢复处理机的运行级为进入睡眠时的值,此时允许中断处理机。
+
+**10.试说明信号与中断两种机制间的异同处。**
+
+答:不同点:中断有优先级,而信号没有,所有信号皆平等;信号处理程序在用户态运行,而中断处理程序是在核心态运行;还有中断响应及时,而信号响应通常都是延时的。
+
+相同点:都采用异步通信方式;当检测出信号或中断请求时都暂停正在执行的程序而转去执行相应的处理程序;都在处理完毕返回到原来断点;对信号或中断都可进行屏蔽。
+
+**11.扼要说明信号机制中信号的发送和对信号的处理功能。**
+
+答:信号发送是指由发送进程把信号送到目标进程的proc结构中信号域的某一位上。对信号的处理功能:首先利用系统调用signal(sig,func)预置对信号的处理方式,func=1时屏蔽该类信号;func=0时,进程收到信号后终止自己;func为非0非1时,func值作为信号处理程序的指针,系统从核心态转为用户态并执行相应的处理程序,处理完毕再返回用户程序的断点处。
+
+**12.什么是管道?无名管道和有名管道的主要差别是什么?**
+
+答:管道是指能连接写进程和读进程,并允许它们以生产者消费者方式进行通信的一个共享文件或pipe文件。无名管道是个临时文件,是利用系统调用pipe()建立起来的无路径名文件,只有调用pipe的进程及其子孙进程才能识别此文件描述符而利用该文件(管道)进行通信;有名管道是利用mknod 系统调用建立的、可以在文件系统中长期存在的有路径名文件,其它进程可以知道其存在,并利用该路径名访问的文件。
+
+**13.在读、写管道时,应遵循哪些规则?**
+
+1. 对pipe文件大小的限制
+
+2. 进程互斥
+
+3. 进程写管道时在管道空间上满足生产者操作规则
+
+4. 进程读管道时在管道空间上满足消费者操作规则
+
+**14.在消息机制中有哪些系统调用?说明它们的用途。**
+
+答:在消息机制中的系统调用是msgctl( )、msgsnd( )、msgrcv( )。
+
+1. msgctl( )系统调用于指定的消息队列进行操纵。
+
+2. msgsnd( )系统调用来发送消息。
+
+3. msgrcv( )系统调用从指定消息队列中读取一个消息。
+
+**15.在共享存储机制中有哪些系统调用?扼要说明它们的用途。**
+
+答:在共享存储机制中的系统调用有shmget() 、shmctl()、shmat()。
+
+1. shmget( )用于建立一块共享存储区,提供该区名字key和共享存储区长度size等参数。
+
+2. shmctl( )系统调用于查询共享存储区的状态信息。
+
+3. shmat( )系统调用于将该共享存储区附接到用户给定的某个进程虚地址shmaddr上,并指定该存储区的访问属性是只读还是可读可写。
+
+**16.核心在执行shmget系统调用时需完成哪些工作?**
+
+1. 检查共享存储区表,若找到key 表项,表明该区已建立,返回共享区描述符shmid;
+
+2. 若未找到指定key 表项,而flag 标志为IPC_CREAT 且参数size值在系统限制值内,则分配一系统空闲区作为共享区的页表区,分配相应的内存块,将这些块号填入页表中;
+
+3. 核心在共享存______xîÿl/___储区和系统区表中,为新建立的共享区分配一空表项,并填上存储区的关键字及大小、共享区页表始址,指向系统区表项指针等,最后返回共享区描述符shmid。
+
+**17.在信号量机制中有哪些系统调用?说明它们的用途。**
+
+答:在信号量机制中的系统调用是senget( )和semop( )。semget()用于用户建立信号量集。semop()用来对信号量集进行操作。
+
+**18.核心是如何对信号量进行操作纵的?**
+
+答:核心根据sem_op改变信号量的值,分3种情况:若sem_op值为正,则将其值加到信号量值上,相当于V操作;若sem_op值为负,相当于P操作,若信号量值大于操作值的绝对值,则核心将一个负整数加到信号量值上,否则核心将已操作的信号量恢复到系统调用开始时的值;若(sem_flg&IPC_NOWAIT)为真,便立即返回,否则让进程睡眠等待。
+
+**19.为实现请求调页管理,在UNIX系统中配置了那些数据结构?**
+
+答:UNIX 系统V 将进程的每个区分为若干个虚页,这些虚页可以分配到不邻接的页框中,为此设置了一张页表。其中每个表项中,记录了每个虚页和页框的对照关系。
+
+**20.当访问的缺页是在可执行文件上或在对换设备上时,应如何将它们调入内存?**
+
+1. 缺页在可执行文件上。如果欲访问虚页对应磁盘块描述表项类型是file,表示该缺页尚未运行,其拷贝在可执行文件中,核心应将该页调入内存。调入过程是:根据对应系统区表项中的索引结点指针,找到该文件的索引节点,把该页的逻辑块号作为偏移量,查找索引结点中的磁盘块号表,找到磁盘块号,将该页调入内存。
+
+2. 缺页在对换设备上。核心先为缺页分配一内存页,修改该页表项,指向内存页,并页面数据表项放入相应散列队列中,把该页从对换设备上调入内存,当I/O操作完成时,核心把请求调入该页的进程唤醒。
+
+**21.在将一页换出时,可分成哪几种情况?应如何处理这些情况?**
+
+1. 若在对换设备上有被换出页的拷贝,内容未改,则核心只将该页页表项中的有效位清零,将引用计数减1,将该页框数据表项放入空闲链表中。
+
+2. 若在对换设备上没有换出页的拷贝,则将该页写到对换设备上。先将所有要换出页链入到待换出页面链上。当链上页面数达到规定值时才将这些页面写到对换区中。
+
+3. 在对换设备上有换出页副本,但页内容已修改,核心应释放该页在对换设备上原占有的空间,再重新将该页拷贝到对换设备上,使拷贝内容最新。
+
+**22.如何对字符缓冲区进行分配与回收?**
+
+答:在字符设备进行I/O 时,内核利用getcf过程从空闲字符缓冲区队列中取得空闲缓冲区,若队列空,则无缓冲区可分配,返回;否则从队首取得一个空闲缓冲区,把该缓冲区指针bp返给调用者。采取互斥访问措施,在过程开始处将处理机优先级提升为6,在取得空缓冲区之后再恢复处理机的优先级。当不再需要缓冲区时,调用putcf过程释放缓冲区。输入参数是指向已不再需要的缓冲区指针bp,把该缓冲区送回到空闲缓冲区队列的队首指针cfreelist指向的头部。此时若有申请空缓冲区而阻塞的进程,则唤醒它。对空闲缓冲区队列的访问应互斥进行。
+
+**23.试说明盘块缓冲区的组成和盘块缓冲池的构成。**
+
+答:UNIX系统的每一个盘块缓冲区均有两部分:一是用于存放数据的数据缓冲区;另一部分是缓冲控制块,用于存放对应缓冲区的管理信息。盘块缓冲池结构:(1)空闲链表(2)散列队列。
+
+**24.getblk()和getblk(dev,blkno)进程的主要区别是什么?**
+
+答:getblk()用于从空闲缓冲区队列中获得任意空闲缓冲区。getblk(dev,blkno)用于为指定设备dev和盘块号为blkno的盘块申请一个缓冲区。仅当要把数据写入特定盘块的内容不在缓冲区时,才调用getblk过程分配一个空缓冲区。
+
+**25.试说明gdopen、gdstart、gdstartegy和gdintr过程的主要功能。**
+
+答:gdopen用于打开磁盘驱动器,输入参数是设备号,无输出参数。gdstart 用于装配磁盘控制器中的各个寄存器,然后启动磁盘控制器。gdstartegy 把指定缓冲首部排在磁盘控制器I/O 队列末尾,并启动磁盘控制器。gdintr用于磁盘I/O传送完成并发出中断请求时的磁盘中断处理过程。
+
+**26.在UNIX系统中设置了哪些读和写过程?两者的主要区别是什么?**
+
+答:读过程有一般读过程bread和提前读过程breada。写过程有一般写过程bwrite、异步写过程bawrite和延迟写过程bdwrite。
+
+**27.试说明UNIX文件系统的特点?**
+
+1.文件系统的组织是分级树形结构形式。
+
+2.文件的物理结构为混合索引式文件结。
+
+3.采用成组链接法管理空闲盘块。
+
+4.引入了索引结点的文件检索技术。
+
+**28.在UNIX系统中的文件物理结构采用了何种形式?试举例说明。**
+
+答:UNIX文件物理结构采用混合索引式文件结构。在查找文件时,只要找到了文件的索引结点,用直接或间接寻址方式获得该文件的盘块。
+
+**29.在UNIX系统中如何将文件的逻辑块号转换为物理盘块号?**
+
+答:寻址方式不同,转换方法也不同。
+
+1. 直接寻址,仅当文件的逻辑块号不大于10时采用。如访问对象是字节偏移量9999处的数据。则9999/1024=9余783,则文件逻辑块号9,直接索引地址项i-addr(9)中的块号,其块内偏移地址为783字节处就是文件的9999字节处。
+
+2. 一次间址,仅当文件的逻辑块号大于10而不大于10+256时采用。如访问对象是字节偏移量18000处的数据。则18000/1024=17余592,则逻辑块号为10<17<10+256,需要通过一次间接索引方式。先从i-addr(10)中得到一次间址盘块号,再将逻辑盘块号减10,根据一次间址中的逻辑块号得到间址块号地址项的下标,再从中得到最终的物理盘块号。这里的逻辑盘块号17,从i-addr(10)中得到的块号设为428,则17-10=7就是一次间址号,其对应的盘块号就是要找的物理盘块号,块内偏移地址为592处就是文件的18000字节处。
+
+3. 多次间址,仅当文件的逻辑块号大于266而不大于64266时采用。如访问对象是字节偏移量420000处的数据。则逻辑块号为266<410<64266,通过二次间址索引。在i-addr(11)中得到一次间址盘块号,再将逻辑盘块号减266,根据一次间址中的逻辑块号得到间址块号地址项的下标,再从中得到二次间址,再找到对应的物理块号,块内偏移地址160处就是文件的420000字节处。
+
+**30.如何对磁盘索引节点进行分配与回收?**
+
+答:分配过程ialloc是:先检查超级块是否上锁,检索i 结点栈空否,从空闲i 结点编号栈中分配一个i结点并初始化,填写有关文件属性,分配内存i结点,将磁盘i结点总数减1,并置超级块修改标志后返回。回收过程ifree是:先检查超级块上锁否;检查i结点编号栈满否;若i 结点编号栈未满,便使回收的i结点的编号进栈,并使当前空闲i 结点数加1;置超级块修改标志后返回。
+
+**31.何时需要构造目录项?核心需完成哪些工作?**
+
+答:当用户(进程)要创建新文件时,内核便应在其父目录文件中构造一个目录项;当某进程需要共享另一用户的某文件时内核也将为共享该文件的用户建立一个目录项。由系统调用creat过程完成目录项的构造。
+
+**32.何时需删除一个目录项?核心须完成哪些工作?**
+
+答:对于某用户独享的文件,当该用户不需要它时,应将它删除而腾出存储空间。核心须完成的工作是利用unlink断开连接,当nlink值为0 时,系统将自动删除该文件。
diff --git a/操作系统/附录2 操作系统总结.md b/操作系统/附录2 操作系统总结.md
new file mode 100644
index 00000000..1df9ec7d
--- /dev/null
+++ b/操作系统/附录2 操作系统总结.md
@@ -0,0 +1,620 @@
+# 基础知识
+> 主要用来总结面试过程中的常见问题
+
+> 参考文献
+> * [操作系统教程总结](https://blog.csdn.net/yanglingwell/article/details/53745758)
+> * [计算机操作系统知识梳理](https://blog.csdn.net/wzk646795873/article/details/79783695)
+
+## 1 操作系统的资源管理技术
+
+* 资源管理解决**物理资源数量不足**和**合理分配资源**这两个问题。
+
+
+
+* 操作系统虚拟机为用户提供了一种简单、清晰、易用、高效的计算机模型。虚拟机的每种资源都是物力资源通过复用、虚拟和抽象而得到的产物。**虚拟机提供进程运行的逻辑计算环境**。从概念上来说,一个进程运行在一台虚拟机上,可以认为一个进程就是一台虚拟机,一台虚拟机就是一个进程。
+
+### 复用:空分复用共享和时分复用共享。
+* 空分复用共享(space-multiplexed sharing): 将资源从“空间”上分割成更小的单位供不同进程使用。在计算机系统中,内存和外存(磁盘)等是空分复用共享的。
+* 时分复用共享(time-multiplexed sharing): 将资源从“时间”上分割成更小的单位供不同进程使用。在计算机系统中,处理器和磁盘机等是时分复用共享的。
+
+### 虚拟:对资源进行转化、模拟或整合。
+
+* 把一个物理资源转变成多个逻辑上的对应物,也可以把多个物理资源变成单个逻辑上的对应物,即创建无须共享独占资源的假象,或创建易用且多于实际物理资源的虚拟资源假象,以达到多用户共享一套计算机物理资源的目的。虚拟技术可用于外部设备(外部设备同时联机操作(SPOOLing)),存储资源(虚拟内存)和文件系统(虚拟文件系统(Virtual File System, VFS))中。
+* 复用和虚拟相比较,复用所分割的是实际存在的物理资源,而虚拟则实现假想的同类资源。**虚拟技术解决某类物理资源不足的问题**,提供易用的虚拟资源和更好的运行环境。
+
+### 抽象:屏蔽硬件资源的物理特性和实现细节
+* 通过创建软件来屏蔽硬件资源的物理特性和实现细节,简化对硬件资源的操作、控制和使用。
+* 复用和虚拟的主要目标是解决**物理资源数量不足的问题**,抽象则用于处理系统复杂性,重点**解决资源易用性**。
+
+## 2 系统调用
+* 系统调用: 为给应用程序的运行提供良好环境,内核提供了一系列具有预定功能的服务例程,通过一组称为**系统调用(System Call)**的接口呈现给用户,系统调用把应用程序的请求传送至内核,调用相应的服务例程完成所需处理,将处理结果返回给应用程序。(注:系统调用的编号称为功能号)
+
+
+
+* 系统调用的执行过程: 当CPU执行程序中编写的 **访管指令(supervisor==自陷指令(trap)==中断指令(interrupt)** 等引起处理器中断的机器指令,实现的系统调用,产生异常信号,通过**陷阱机制**(也称**异常处理机制**,当异常或中断发生时,处理器捕捉到一个执行线程,并且将控制权转移到操作系统中某一个固定地址的机制),处理器的状态由用户态(user mode, 又称目态或普通态)转变为内核态(kerbel mode, 又称管态),进入操作系统并执行相应服务例程,以获得操作系统服务。当系统调用执行完毕时,处理器再次切换状态,控制返回至发出系统调用的程序。
+
+* 系统调用是应用程序获得操作系统服务的唯一途径。
+
+### 系统调用的作用:
+
+1. 内核可以基于权限和规则对资源访问进行裁决,保证系统的安全性。
+2. 系统调用对资源进行抽象,提供一致性接口,避免用户在使用资源时发生错误,且编程效率大大提高。
+
+### 系统调用与函数调用的区别:
+
+* 调用形式和实现方式不同。功能号 VS 地址; 用户态转换到内核态 VS 用户态。
+* 被调用代码的位置不同。 动态调用 + 操作系统 VS 静态调用 + 用户级程序。
+* 提供方式不同。 操作系统 VS 编程语言。
+
+## 3 操作系统内核
+
+### 定义
+* 内核: 是一组程序模块,作为可信软件来提供支持进程并发执行的基本功能和基本操作,通常驻留在内核空间,运行于内核态,具有直接访问硬件设备和所有内存空间的权限,是仅有的能够执行特权指令的程序。
+
+## 内核的功能
+1. 中断处理。中断处理是内核中最基本的功能,也是操作系统赖以活动的基础。
+2. 时钟管理。时钟管理是内核的基本功能。
+3. 短程调度。短程调度的职责是分配处理器,按照一定的策略管理处理器的转让,以及完成保护和恢复现场工作。
+4. 原语管理。 原语是内核中实现特定功能的不可中断过程。
+
+* 内核是操作系统对裸机的第一次改造,内核和裸机组成了第一层虚拟机,进程在虚拟机上运行。
+
+## 4 处理器状态:内核态和用户态
+### 概念
+* 仅在内核态下才能使用的指令称为特权指令,执行这些指令不仅影响运行程序自身,而且还会干扰其他程序及操作系统。 非特权指令在内核态和和用户态下都能工作。
+* 现代计算机为处理器建立硬件标志位,称处理器状态位,通常是**程序状态字(Program Status Word, PSW)**中的一位,来将处理器的状态设置为内核态或用户态。
+
+### 用户态向内核态转换的情况:
+1. 程序请求操作系统服务, 执行系统调用。
+2. 在程序运行时产生中断事件(如I/O操作完成),运行程序被中断,转向**中断处理程序**处理。
+3. 在程序运行时产生异常事件(如在目态下执行特权指令),运行程序被打断,转向**异常处理程序**工作。
+
+> 以上三种情况都是通过中断机制发生,可以说中断和异常是用户态到内核态转换的仅有途径。
+
+### 用户栈和核心栈
+1. 用户栈是用户进程空间中的一块区域。用于保存应用程序的子程序(函数)间相互调用的参数,返回值,返回点和子程序的局部变量。
+2. 核心栈是内存中操作系统空间的一块区域。用于保存中断现场和保存操作系统程序(函数)间相互调用的参数,返回值,返回点和程序的局部变量。
+
+## 5 中断(Interupt)
+
+### 定义
+* 中断:程序执行过程中遇到急需处理的事件时,暂时终止现行程序在CPU上的运行,转而执行相应的**事件处理程序**,待处理完成后再返回断点或调度其他程序的执行过程。
+
+### 中断的分类:
+1. 外中断(又称中断或异步中断): 来自处理器之外的中断信号,如,时钟中断、键盘中断等。外中断可分为可屏蔽中断和非可屏蔽中断。
+2. 内中断(又称异常或同步中断),来自处理器内部的中断信号,如,访管中断,硬件故障中断,程序性中断等。内中断不能被屏蔽。
+
+### 中断和异常的响应:
+
+* 发现中断源 → 保护现场 → 转向(中断/异常)事件处理程序执行 → 恢复现场
+
+## 6 进程
+
+### 定义
+* 进程:具有独立功能的程序在某个数据集合上的一次运行活动,也**是操作系统进行资源分配和保护的基本单位** 。
+1. 从原理角度看,进程是支持程序执行的一种系统机制,它对处理器上运行程序的活动进行抽象。
+2. 从实现角度看,进程是一种数据结构,用来准确地刻画运行程序的状态和系统动态变化状况。
+
+### 进程状态的七态模型
+
+
+
+1. 新建态(new): 进程被创建,尚未进入就绪队列。
+1. 就绪态(ready): 进程具备运行条件,等待系统分配处理器。
+1. 挂起就绪态(ready suspend):进程具备运行条件,但目前在外存中。
+1. 运行态(running): 进程占有处理器正在运行。
+1. 终止态(exit): 进程达到正常结束点或被其他原因所终止,下一步将被撤销。
+1. 等待态(wait): 又称阻塞态或休眠态。进程正在等待某个事件完成,目前不具备运行条件。
+1. 挂起等待态(blocked suspend): 进程正在等待某个事件完成,并且在外存中。
+
+### 概述
+* 程序和数据刻画进程的静态特征,称为进程控制块的一种数据结构刻画进程的动态特征。**进程映像(process image)** 包括进程控制块、进程程序块、进程核心块、进程数据块等要素。
+
+* 进程控制块(Process Control Block, PCB):进程存在的唯一标识,操作系统掌握进程的唯一资料结构和管理进程的主要依据。包括标识信息、现场信息和控制信息等信息。
+
+* 进程队列(process queue):处于同一状态的所有进程的PCB链接在一起的数据结构。 有两种队列组织方式:链接方式和索引方式。
+
+* 进程切换必定在内核态而非用户态发生。
+
+* 进程可以分为两部分,资源集合和线程集合。进程要支撑线程运行,为线程提供虚拟地址空间和各种资源。进程封装管理信息,线程封装执行信息。
+
+
+
+## 7 处理器调度
+
+### 处理器调度层次:
+
+
+
+1. **高级调度**: 又称作业调度、长程调度。从输入系统的一批 **作业(job, 用户提交给操作系统计算的一个独立任务)** 中按照预定的调度策略挑选若干作业进入内存,为其分配所需资源并创建对应作业的用户进程。
+2. **中级调度**: 又称平衡调度,中程调度。根据内存资源情况决定内存所能容纳的进程数目,并完成外存和内存中进程对换工作。
+3. **低级调度**:又称进程调度/线程调度,短程调度。根据某种原则决定就绪队列中那个进程/线程先获得处理器,并将处理器出让给它使用。
+
+### 低级调度算法:
+1. 先来先服务(First Come First Server, FCFS)算法。
+3. 最短作业优先(Shortest Job First, SJF)算法。
+3. 最短剩余时间优先(Shortest Remaining Time First, SRTF)算法: 假设当前某进程/线程正在运行,如果***有新进程/线程移入就绪队列***,若它所需的CPU运行时间比当前运行的进程/线程所需的剩余CPU时间还短,抢占式最短作业优先算法强行剥夺当前执行者的控制权,调度新进程/线程执行。
+4. 最高响应比优先(Highest Response Ratio First, HRRF)算法:非剥夺式算法。其中,响应比 = (作业已等待时间 + 作业处理时间) / 作业处理时间。
+5. 优先级调度算法:优先级高的选择进程/线程优先选择。
+6. 轮转调度(Round-Robin, RR)算法: 也称时间片调度。就绪队列的进程轮流运行一个时间片。
+7. 多级反馈队列(Multi-Level Feedback Queue, MLFQ)算法。
+
+### 衡量调度算法的性能指标:
+1. 资源利用率: CPU利用率 = CPU有效工作时间/(CPU有效工作时间 + CPU空闲等待时间)
+2. 吞吐率: 单位时间内CPU处理作业的个数。
+3. 公平性: 确保每个进程都能获得合理的CPU份额和其他资源份额,不会出现饥饿现象。
+4. 响应时间: 从交互式进程提交一个请求(命令)直到获得响应之间的时间间隔。
+5. 周转时间: 批处理用户从向系统提交作业开始到作业完成为止的时间间隔。平均周转时间:$T=(\sum_{i=1}^n t_i)/n$ , 其中 $t i$表示作业i的周转时间。平均带权作业周转时间: $T = ( \sum_{i=1}^n w_i ) / n$, 其中 $w_i = t_i / t_k$ 表示作业i的周转时间。 $t_k$表示作业i的运行时间。
+
+## 8 进程的交互
+### 概述
+* **进程互斥(Mutual Exclusion)**: 若干进程因相互抢夺独占型资源而产生的竞争制约关系。
+
+* **进程同步(Synchronization)**: 为完成共同任务的并发进程基于某个条件来协调其活动,因为需要在某些位置上排定执行的先后次序而等待、传递信息或消息所产生的协作制约关系。
+
+### 资源竞争会引发两个控制问题:
+1. **死锁**:一组进程因争夺资源陷入永远等待的状态。
+2. **饥饿**:一个可运行进程由于由于其他进程总是优先于它,而被调度程序无限期地拖延而不能被执行。
+
+## 9 临界区管理
+
+### 概念
+* 并发进程中与共享变量有关的程序段称为临界区(Critical Section)。共享变量所代表的资源称为临界资源(Critical Resource),即一次仅能供一个进程使用的资源。
+
+### 临界区调度原则:
+1. 择一而入。 一次之多只有一个进程进入临界区内执行。
+2. 忙则要等。 如果已有进程在临界区中, 试图进入此临界区的其他进程应等待。
+3. 有限等待。 进入临界区内的进程应在有限时间内退出。
+
+### 临界区管理的软件算法:Peterson算法。
+* 为每个进程设置标志,当标志值为 true 时表示该进程要求进入临界区,另外再设置一个指示器 turn 以指示可以由哪个进程进入临界区,当 turn = i 时则可由 Pi 进入临界区。
+```C++
+/* Peterson 算法 */
+
+bool inside[2];
+inside[0] = false;
+inside[1] = false;
+enum { 0, 1 } turn;
+
+/* 进程0 */
+process P0(){
+inside[0] = true; //请求...
+ turn = 1;
+ while(inside[1] && turn == 1) ; //等待...
+
+ /*临界区 */
+
+ inside[0] = false; //归还...
+}
+
+/* 进程1 */
+process P1(){
+inside[1] = true; //请求...
+ turn = 0;
+ while(inside[0] && turn == 0) ; //等待...
+
+ /*临界区 */
+
+ inside[1] = false; //归还...
+}
+```
+
+> Peterson算法满足临界区管理的三个原则。
+
+### 临界区管理的硬件设施:
+1. 关中断。 在进程进入临界区时关中断,进程退出临界区时开中断。
+2. . 测试并设置指令。 利用机器指令TS(Test and Set)实现临界区的上锁和开锁原语操作。
+3. 对换指令。 利用对换指令实现临界区的上锁和开锁原语操作。
+
+## 10 信号量(samaphore)和PV操作
+### 说明
+PV操作都是原语操作, 不可中断。
+
+### 信号量和PV操作
+* 信号量
+```
+// 信号量
+typedef struct semaphore {
+ int value; // 信号量值
+ struct pcb* list; // 指向“等待该信号量的进程队列”的指针
+};
+```
+* P操作
+```
+// P操作
+void P(semaphore s){
+ s.value--; // 信号量值减一
+
+ // 如果信号量值小于0, 执行P操作的进程调用sleep(s.list)阻塞自己,
+ // 被置成“等待信号量s”状态,并移入s信号量队列,转向进程调度程序。
+ if(s.value < 0) sleep(s.list);
+}
+```
+* V操作
+```
+// V操作
+void V(semaphore s){
+ s.value++; // 信号量值加一
+
+ // 如果信号量小于等于0, 则调用wakeup(s.list)释放一个等待信号量s的进程,
+ // 并转换成就绪态, 进程则继续执行。
+ if(s.value <= 0) wakeup(s.list);
+}
+```
+1. 若信号量值 s.value 为正值, 此值等于在封锁进程之前对信号量 s 可施行P操作的次数,即,s所代表的实际可用的资源数。
+2. 若信号量值 s.value 为负值, 其绝对值等于登记在 s 信号量队列中的等待进程的数目。
+3. 通常**P操作意味着请求一个资源**,**V操作意味着释放一个资源**。在一定条件下,P操作也可表示挂起进程的操作,V操作代表唤醒被挂起进程的操作。
+
+### 信号量实现互斥
+```
+semaphore mutex;
+mutex = 1;
+
+//进程Pi, i = 1, 2 ..., n
+process Pi(){
+ P(mutex);
+
+ /* 临界区 */
+
+ V(mutex);
+}
+```
+## 11 管程
+### 概念
+* 管程(monitor):代表**共享资源的数据结构和在其上执行的一组并发进程**就构成管程,管程被请求和释放资源的进程锁调用。
+* 信号量机制的缺点:进程自备同步操作,P(S)和V(S)操作大量分散在各个进程中,不易管理,易发生死锁。
+* 管程特点:管程封装了同步操作,对进程隐蔽了同步细节,简化了同步功能的调用界面。用户编写并发程序如同编写顺序(串行)程序。
+
+### 引入管程机制的目的:
+
+1. 把分散在各进程中的临界区集中起来进行管理
+2. 防止进程有意或无意的违法同步操作;
+3. 便于用高级语言来书写程序,也便于程序正确性验证。
+
+
+### 实现
+
+
+1. 条件变量。 管程内的一种数据结构。只有在管程中才能被访问,进程可以在条件变量上等待或被唤醒。只能通过 wait() 和 signal() 原语操作来控制。
+2. wait()原语。 挂起调用进程并释放管程,直至另一个进程在条件变量上执行 signal()。
+3. signal() 原语。如果有其他的进程因对条件变量执行 wait() 而被挂起,便释放之。 如果没有进程在等待,那么相当于空操作,信号不被保存。
+
+## 12 死锁
+
+### 死锁的主要解决方法
+
+1. 死锁防止
+1. 死锁避免
+1. 死锁检测和恢复。
+
+### 死锁产生的必要条件:
+1. 互斥条件。 临界资源是独占资源,进程应互斥且排他地使用这些资源。
+2. 占有等待条件。 进程在请求资源得不到满足而等待时,不释放已占有的资源。
+3. 不剥夺条件。已获资源只能由进程资源释放,不允许被其他程序剥夺。
+4. 循环等待条件。 存在循环等待链,其中每个进程都在等待下一个进程所持有的资源。
+
+### 死锁的防止
+* 破坏死锁产生的必要条件。
+ * 使资源可同时使用(破坏互斥条件)、
+ * 静态分配资源(破坏占有和等待条件)、
+ * 剥夺调度(破坏不剥夺条件)、
+ * 层次分配策略(循环等待条件)等。
+
+### 死锁避免:
+* 银行家算法
+
+### 死锁检测和恢复:
+* 进程-资源分配图(额…还是去百度吧。)
+ * 如果进程-资源分配图中无环路,此时系统没有死锁。
+ * 如果进程-资源分配图中有环路,且每个资源类中只有一个资源,则系统发生死锁。
+ * 如果进程-资源分配图中有环路,且所涉及的资源类有多个资源,则不一定会发生死锁。
+
+## 13 可变分区存储管理
+### 可变分区存储分配算法:
+1. 最先适应分配算法。从未分配区的开始位置开始扫描,在找到的第一个能满足长度要求的空闲区上分配存储空间。
+2. 下次适应分配算法。从未分配区上次扫描结束处开始顺序查找,在找到的第一个能满足长度要求的空闲区上分配存储空间。
+3. 最优适应分配算法。扫描整个未分配区,选择能满足用户进程要求的最小分区分配存储空间。
+4. 最坏适应分配算法。扫描整个未分配区,选择能满足用户进程要求的最大分区分配存储空间。
+5. 快速适应分配算法。为经常用到的长度的空闲区设立单独的空闲区链表。
+
+## 14 分页存储管理
+### 基本概念:
+1. 页面。 进程逻辑地址空间分成大小相等的区,每个区称为页面或页。(页面的本质是逻辑地址空间)
+2. 页框。 又称页帧。内存物理地址空间分成大小相等的区,其大小和页面大小相等,每个区就是一个页框。(页框的本质是物理地址空间)
+3. 逻辑地址。分页存储器的逻辑地址由页号和页内偏移两部分组成。
+
+4. 内存页框表。页框表的表项给出物理块使用情况:0为空闲,1为占用。
+5. 页表。页表是操作系统为进程建立的,是程序页面和内存页框的对照表,页表的每一栏指明程序中的某一页面和分得的页框之间的关系。
+
+### 分页存储管理的地址转换
+
+* 翻译快表:也称转换后援缓冲(Translation Look_aside Buffer, TLB)。用来存放进程最近访问的部分页表项。(翻译快表之于页表类似于Cache之于存储器)
+
+* 二级页表:把整个页表分割成许多小页表,每个称为页表页,每个页表页含有若干个页表表项。页表页允许分散对应不连续的页框。为了找到页表页,应建立地址索引,称为页目录表,其表项指出页表页起始地址。
+* 二级页表实现逻辑地址到物理地址转换的过程: 由硬件“页目录表基址寄存器”指出当前运行进程的页目录表的内存起始地址,加上“页目录位移”作为索引,可找到页表页在内存的起始地址,再以“页目录位移”作为索引,找到页表页在内存的起始位置,再以“页表页位移”作为索引,找到页表页的表项,此表项中包含一个页面对应的页框号,由页框号和页内偏移便可生成物理地址。
+
+
+* 类比于书的目录,找某一段内容的时候,先在目录上找到对应的章节,再在对应的章节下面找具体的知识点。比如,我要在《操作系统原理》中查“多级页表”。首先我知道它是在存储管理一章的,于是就找到了“第四章 存储管理”(类似于找到了页目录表)。 然后在第四章下面找“多级页表”(类似于在页目录表下面找具体的页表页)。最后找到“多级页表”对应的页码(类似于在页表页中找到其对应的页框)。最后查阅对应的章节页码(类似于读取对应页框的数据)。
+
+## 15 分段存储管理
+
+
+### 分段和分页的比较:
+1. 分段是信息的逻辑单位,由源程序的逻辑结构及含义所决定,是用户可见的,段长由用户根据需要来确定,段起始地址可以从任何内存地址开始。引入的目的是满足用户模块化程序设计的需要。
+2. 分页是信息的物理单位,与源程序的逻辑无关,是用户不可见的,页长由系统(硬件)决定,页面只能从页大小的整数倍地址开始。引入目的是实现离散分配并提高内存利用率。
+
+## 16 虚拟存储管理
+### 虚拟存储管理的基本思路:
+
+
+
+* 把磁盘空间当做内存的一部分,进程的程序和数据部分放在内存中,部分放在磁盘上。程序运行时,它执行的指令或访问的数据在哪里由存储管理负责判断,并针对情况采取响应的措施。
+
+### 请求分页虚存管理
+* 将进程信息副本存放在外存中,当它被调度投入运行时,程序和数据没有全部装进内存,仅装入当前使用页面,进程执行过程中访问到不在内存的页面时,产生缺页异常,再由系统自动调入。
+
+### 全局页面替换策略
+> 页面替换算法的作用范围是整个系统,不考虑进程的属主:
+1. 最佳页面替换算法(Optimal Replacement, OPT)。 淘汰不再访问的页或者距现在最长时间后才访问的页。
+2. 先进先出页面替换算法(First in First Out Replacement, FIFO)。淘汰在内存中驻留时间最长的页。
+3. 最近最少使用页面替换算法(Least Recently Used Replacement, LRU)。 淘汰最近一段时间内最久未被使用的页面。
+4. 第二次机会页面替换算法(Second Chance Replacement, SCR)。 首先检查FIFO页面队列中的队首,这是最早进入内存的页面,如果其“引用位”为0,那么它最早进入且未被引用,此页被淘汰。如果其“引用位”为1,说明虽然它最早进内存,但最近仍在使用,于是将“引用位”清零,并把这个页面移到队尾,把它看做新调入的页面,再给它一次机会。
+5. 时钟页面替换算法(Clock Policy Replacement, Clock)。与SCR算法思路一致。只是用循环队列来构造页面队列,队列指针指向可能被淘汰的页面。如果队列指针指向的页的“引用位”为1,则将其置为0,同时队列指针指向下一个页。
+
+### 局部页面替换算法
+> 页面替换算法的作用局限于进程自身,要为进程维护称为工作集的一组页面:
+1. 局部最佳页面替换算法(Local Minimum Replacement, MIN)。 在t时刻时,若页面P在未来(t, t+delta)时间段内未被引用,则它被淘汰。
+2. 工作集置换算法。 在t时刻时,若页面P在未来(t-delta, t)时间段内未被引用,则它被淘汰。
+3. 模拟工作集替换算法。
+4. 缺页频率替换算法。
+
+## 17 请求段页式虚拟内存管理
+* 虚地址以程序的逻辑结构划分为段。
+* 实地址划分为位置固定、大小相等的页框(块)。
+* 逻辑地址分为三个部分:段号s、段内页号p、页内位移d。对于用户而言,段式虚拟地址应该由段号s和段内位移d’组成,操作系统内部自动把d’解释成段内页号p和页内位移号d。
+
+## 18 I/O硬件原理:I/O控制方式
+
+### 轮询方式
+* 又称程序直接控制方式。使用查询指令测试设备控制器的忙闲状态位,确定内存和设备是否能能交换数据。(@杨领well注:所谓轮询,就好比,老湿依次问每一个童鞋:“有问题没?”, 如果没问题,就继续问下一个童鞋。如果这个童鞋有问题,这个老湿就停下了解决这个问题。然后又继续询问下一个童鞋。)
+
+### 中断方式
+* 要求CPU和设备控制器及设备之间存在中断请求线,设备控制器的状态寄存器有相应的中断允许位。
+1. 进程发出启动I/O指令。
+2. 设备控制器检查状态寄存器的内容,执行相应的I/O操作,一旦传输完成,设备控制器通过中断请求线发出I/O中断信号。
+3. CPU收到并响应I/O中断后,转向设备的I/O中断处理程序执行。
+4. 中断处理程序执行数据读取操作,将I/O缓冲寄存器的内容写入内存。操作结束后退出中断程序恢复之前的状态。
+5. 执行中断前之前运行的进程。(类似于老湿在上面讲课,有童鞋问问题时,老湿就记录下自己讲到的位置,然后取回答童鞋的问题,回答完之后,又回到刚刚讲课的地方继续讲课)
+
+### DMA(Direct Memory Access, 直接存储器存取)方式
+
+* 内存和设备之间有一条数据通路成块的传输数据,无须CPU干9预,实际数据传输操作由DMA直接完成。
+
+### 通道方式
+* CPU在执行主程序时遇到I/O请求,启动在指定通道上选址的设备,一旦启动成功,通道开始控制设备进行操作,这时CPU就可以执行其他任务并与通道并行工作,直到I/O操作完成;当通道发出I/O操作结束中断时,处理器才响应并停止当前工作,转而处理I/O操作结束时间。
+
+## 19 I/O软件原理
+* I/O中断处理程序: 通常是设备驱动程序的组成部分之一。检查设备状态寄存器内容,判断产生中断原因,根据I/O操作的完成情况进行相应处理。若数据传输有错,应向上层软件报告设备出错信息,实施重新执行;若正常结束,应唤醒等待传输的进程,使其转换为就绪态;若有等待传输的I/O命令,应通知相关软件启动下一个I/O请求。
+* I/O设备驱动程序:设备驱动程序是设备专有的。把用户提交的逻辑I/O请求转化为物理I/O的启动和执行。同时监督设备是否正确执行,管理数据缓冲区,进行必要的纠错处理。
+* 独立于设备的I/O软件
+* 用户空间的I/O软件
+
+## 20 缓冲技术
+> 这里是指cache。缓存。而不是缓冲buffer。cache的本命缓冲存储器。本质上是一个存储器。
+### 缓冲技术的基本思想
+* 当进程执行写操作输出数据时,先向系统申请一个输出缓冲区,然后将数据送至缓冲区,若是顺序写请求,则不断地把数据填入缓冲区,直至装满为止,此后进程可以继续计算,同时,系统将缓冲区的内容写在设备上。当进程执行读操作输入数据时,先向系统申请一个输入缓冲区,系统将设备上的一条物理记录读至缓冲区,根据要求把当前所需要的逻辑记录从缓冲区中选出并传送给进程。
+
+### 单缓冲
+
+* 是最简单的缓冲技术,每当有I/O请求时,操作系统就在内存的系统区中开设一个缓冲区。不允许多个进程同时对一个缓冲器操作。
+
+
+
+* 双缓冲: CPU可把输出到设备的数据放入其中一个缓冲器(区)、让设备慢慢处理;然后,它又可以从另一个为终端设置的缓冲器(区)中读取所需要的输入数据。
+
+
+
+* 多缓冲: 是把多个缓冲区连接起来组成两部分,一部分专门用于输入,另一部分专门用于输出的缓冲结构。
+
+
+
+## 21 驱动调度技术
+
+### 磁盘的物理结构:
+
+* 磁盘包括多个盘面,每个盘面有一个读写磁头,所有的磁头都固定在唯一的移动臂上同时移动。一个盘面上的读写磁头的轨迹称为磁道,读写磁头下的所有磁道形成柱面,一个磁道又可以划分为多个扇区。在磁盘上定位某个物理记录需要知道其柱面号、磁头号以及扇区号。定位物理记录时,磁头到达指定扇区的时间称为查找时间, 选择磁头号并旋转至指定扇区的时间称为搜索延迟。
+### 磁道(柱面)的搜索定位算法:
+1. 先来先服务算法(First Come First Server algorithm, FCFS)。
+2. 最短查找时间优先算法: 总是执行查找时间最短的请求。
+3. 扫描算法: 移动臂来回的扫过所有柱面,扫描处遇到I/O请求便进行处理。
+4. 分步扫描算法: 将I/O请求分为长度为N的子队列,按FIFO算法依次处理每个队列,而每个子队列采用扫描算法,处理完一个后再服务下一个队列。
+5. 电梯调度算法: 又称LOOK算法。
+
+### 磁头号由外向内递增。
+6. 循环扫描算法: 移动臂总是从0号柱面至最大号柱面顺序扫描,然后直接返回0号柱面重复进行,归途中不提供服务(而扫描算法归途是要提供服务的)。
+
+## 22 设备独立性
+* 设备独立性: 用户通常不指定物理设备,而是指定逻辑设备,使得用户作业和物理设备分离开来,再通过其他途径建立逻辑设备和物理设备之间的映射,设备的这种特性称为设备独立性。
+
+## 23 虚拟设备
+### 外部设备同时联机操作(Simultaneous Peripheral Operations On Line, SPPPLing):
+1. 预输入程序。 控制信息从输入设备至输入井,填写预输入表以便在作业执行过程中要求输入信息时可以随时找到其存放位置。
+2. 井管理程序。 作业执行过程中要求启动某台设备进程I/O操作时,作业控制程序截获这个要求并调用井管理程序控制从相应输入井读取信息,或将信息送至输出井。
+3. 缓输出程序。 当处理器空闲时,操作系统调用缓输出程序执行缓输出,它查看缓输出表是否有输出打印的文件,文件打印前还可能组织作业或文件标题,也可能对从输出井中读出的信息进行格式加工。
+
+## 24 文件逻辑结构
+### 文件的逻辑结构的两种形式:
+1. 流式文件。 一种无结构的文件,文件内的数据不再组成记录,只是一串顺序的信息集合,称为字节流文件。
+2. 记录式文件。 一种有结构的文件,包含若干逻辑记录,逻辑记录是文件中按信息在逻辑上独立含义所划分的信息单位。
+
+## 25 文件物理结构
+* 文件物理结构: 文件的物理结构和组织是指逻辑文件在物理存储空间中的存放方法和组织关系。
+* 常见组织方式:顺序文件、连接文件、直接文件和索引文件。
+
+
+## 26 Q&A
+### 1 什么是操作系统?操作系统在计算机系统中的主要作用是什么?
+* 定义: 操作系统尚无严格的定义。 一般可把操作系统定义为: 管理系统资源、控制程序执行、改善人机界面、提供各种服务,并合理组织计算机工作流程和为用户方便有效地使用计算机提供良好的运行环境的一种软件系统。
+
+* 作用:
+ 1. 服务用户。 操作系统作为用户接口和公共服务程序。
+ 2. 进程交互。 操作系统作为进程执行的控制者和协调者。
+ 3. 系统实现。 操作系统作为扩展机或虚拟机。
+ 4. 资源管理。 操作系统作为资源的管理者和控制者。
+
+### 2 什么是多道程序设计?多道程序设计有什么特点?
+* 多道程序设计(multiprogramming): 允许多个作业(程序)同时进入计算机系统的内存并启动交替计算的方法。
+* 多道程序设计的特点: 从宏观上看是并行的,从微观上看是串行的。
+
+### 3 计算机操作系统为什么引入进程?
+* 刻画程序的并发性。
+* 解决资源的共享性。
+
+### 4 在分时系统中,什么是响应时间?它与哪些因素有关?
+* 从交互式进程提交一个请求(命令)直到获得响应之间的时间间隔称为响应时间。
+* 影响分时操作系统的响应时间的因素很多,如,CPU的处理速度、联机终端的数目、所用时间片的大小、系统调度开销和对换信息量的多少等。
+### 5 解释并发性与并行性
+* 计算机操作系统中把并行性和并发性明显区分开,主要是从微观的角度来说的,具体是指进程的并行性(多处理机的情况下,多个进程同时运行)和并发性(单处理机的情况下,多个进程在同一时间间隔运行的)。
+ * 并行性是指硬件的并行性,两个或多个事件在同一时刻发生。
+ * 并发性是指进程的并发性,两个或多个事件在同一时间段内发生。
+### 6 试述存储管理的基本功能。
+* 存储分配。
+* 地址映射。
+* 存储保护。
+* 存储共享。
+* 存储扩充。
+### 7 何谓地址转换(重定向)?哪些方法可以实现地址转换?
+* 地址重定位: 又称地址转换,地址映射。 可执行程序逻辑地址转换(绑定)为物理地址的过程。
+
+* 实现方法:
+ 1. 静态地址重定位。 由装载程序实现装载代码模块的加载和地址转换,把它装入分配给进程的内存指定区域,其中的所有逻辑地址修改成内存物理地址。
+ 2. 动态地址重定位。由装载程序实现装载代码模块的加载和地址转换,把它装入分配给进程的内存指定区域,但对链接程序处理过的应用程序的逻辑地址则不做任何修改,程序内存起始地址被置于硬件专用寄存器 —— 重定位寄存器。程序执行过程中,每当CPU引用内存地址(访问程序和数据)时,由硬件截取此逻辑地址,并在它被发送到内存之前加上重定位寄存器的值,以便实现地址转换。
+ 
+ 3. 运行时链接地址重定位
+
+### 8 程序链接的三种方式:
+1. 静态链接。在程序装载到内存和运行前,就已将它的所有目标模块及所需要的库函数进行链接和装配成一个完整的可执行程序且此后不可拆分。
+2. 动态链接。在程序装入内存前并未事先进行程序各目标模块的链接,而是在程序装载时一边装载一边链接,生成一个可执行文件。
+3. 运行时链接。 将某些目标模块或库函数的链接 推迟到执行时才进行。
+
+### 9 什么是文件的共享?介绍文件共享的分类和实现思想。
+* 文件共享: 不同进程共同使用同一个文件。
+* 文件共享的分类:
+ 1. 静态共享。 两个或多个进程通过文件链接(一个文件同时属于多个目录,但实际上仅有一处物理存储)达到共享同一个文件的目的,无论进程是否运行,其文件的链接关系都是存在的,因此称为静态共享。
+ 2. 动态共享。 系统不同的应用程序或同一用户的不同进程并发地访问同一文件,这种共享关系只有当进程存在时才可能出现,一旦进程消亡,其共享关系也就随之消失。
+ 3. 符号链接共享。
+
+
+
+### 10 进程和线程以及它们的区别
+
+1. 进程是对运行时程序的封装,是系统进行资源调度和分配的基本单位,实现操作系统的并发。
+2. 线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发。
+3. 一个程序至少有一个进程,一个进程至少有一个线程,线程依赖进程的存在。
+4. 进程执行过程中拥有独立的内存单元,而多个线程共享进程的内存。
+
+### 11 进程间的通信的几种方式
+1. 管道(pipe)及命名管道(named pipe):管道可用于具有亲缘关系的父子进程间通信,命名管道除了具有管道所具有功能外,还允许无亲缘关系进程的通信。
+
+2. 信号(signal):是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
+
+3. 消息队列:是消息的链接表,克服上两种通信方式中信号量有限的缺点,具有写权限的进程可以按照一定规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。
+
+4. 共享内存:最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。
+
+5. 信号量:主要作为进程之间及同一种进程的不同线程之间的同步和互斥手段。
+
+6. 套接字:这是一致性更为一般进程间通信机制,它可用网络中不同机器之间进程间通信,应用非常广泛。
+
+### 12 线程同步的方式
+1. 互斥量Synchronized/lock:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
+
+2. 信号量Semaphore:它允许同一时刻多个线程访问同一资源,但需要控制同一时刻访问此资源的最大线程数。
+
+3. 事件(信号),Wait/Notify:通过通知操作的方式来保存多线程同步,还可以方便的实现多线程优先级比较操作。
+
+### 13 什么是死锁?死锁产生的条件?
+* 死锁的概念:
+ * 在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗讲,就是两个或者多个进程无限期的阻塞、相互等待的一种状态。
+
+* 死锁产生的四个必要条件
+ * 互斥:至少有一个资源必须属于非共享模式,即一次只能被一个进程使用;若其他申请使用该资源,那么申请进程必须等到该资源被释放为止;
+ * 占用并等待:一个进程必须占有至少一个资源,并等待另一个资源,而该资源为其他进程所占有;
+ * 非抢占;进程不能被抢占,即资源只能被进程在完成任务后资源释放。
+ * 循环等待:若干进程之间形成一种头尾相接的环形等待资源关系。
+
+* 死锁处理的基本策略和常用方法:解决死锁的基本方法主要有:预防死锁,避免死锁,检测死锁,解除死锁等思想。
+ * 死锁预防。死锁预防基本思想:只要确保死锁发生的四个必要条件至少有一个不成立,就能预防死锁。
+ * 打破互斥条件:允许进程同时访问某些资源。但是,有些资源是不能被多个进程所共享的,这是由资源本身属性所决定的,因此,这种办法通常并无实用价值。
+ * 打破占用并等待条件:可以实行资源预先分配策略(进程在运行前一次性向系统申请它所需要的全部资源,若所需全部资源得不到满足,则不分配任何资源,此进程暂不运行;只有当系统能满足当前进程所需的全部资源时,才一次性将所申请资源全部分配给该线程)或者只允许进程在没有占用资源时才可以申请资源(一个进程可申请一些资源并使用它们,但是在当前进程申请更多资源之前,它必须全部释放当前所占有的资源)。但是这种策略也存在一些缺点:在很多情况下,无法预知一个进程执行前所需的全部资源,因为进程是动态执行的,不可预知的;同时,会降低资源利用率,导致降低了进程的并发性。
+ * 打破非枪占条件:允许进程强行从占有者哪里夺取某些资源,也就是说,但一个进程占有了一部分资源,在其申请新的资源且得不到满足时,它必须释放所有占有的资源以便让其它线程使用。这种预防死锁的方式实现起来困难,会降低系统性能。
+ * 打破循环等待条件:实行资源有序分配策略。对所有资源排序编号,所有进程对资源的请求必须严格按资源序号递增的顺序提出,即只有占用了小号资源才能申请大号资源,这样就不回产生环路,预防死锁的发生。
+ * 死锁避免:死锁避免的基本思想是动态检测资源分配状态,以确保循环等待条件不成立,从而确保系统处于安全状态。所谓安全状态是指:如果系统能按某个顺序为每个进程分配资源(不超过其最大值),那么系统状态是安全的,换句话说就是,如果存在一个安全序列,那么系统处于安全状态。资源分配图算法和银行家算法是两种经典的死锁避免的算法,其可以确保系统始终处于安全状态。其中,资源分配图算法应用场景为每种资源类型只有一个实例(申请边,分配边,需求边,不形成环才允许分配),而银行家算法应用于每种资源类型可以有多个实例的场景。
+ * 死锁解除:死锁解除的两种常用方法为进程终止和资源抢占。所谓进程终止是指简单地终止一个或多个进程以打破循环等待,分终止所有死锁进程、一次只终止一个进程直到取消死锁循环为止。所谓资源抢占就是指从一个或多个死锁进程哪里抢占一个或多个资源,此时需考虑三问题
+ * 选择一个牺牲品。
+ * 回滚到安全状态
+ * 饥饿(在代价因素中加上回滚次数,回归的越多则越不可能作为牺牲品,避免一个进程总是被回滚)。
+
+### 14 进程有哪几种状态?
+* 就绪状态:进程已获得除处理机以外的所需资源,等待分配处理机资源;
+* 运行状态:占用处理机资源运行,处于此状态的进程数小于等于CPU数;
+* 阻塞状态:进程等待某种条件,在条件满足之前无法执行;
+
+ 
+
+### 15 线程有几种状态?
+* 在 Java虚拟机 中,线程从最初的创建到最终的消亡,要经历若干个状态:创建(new)、就绪(runnable/start)、运行(running)、阻塞(blocked)、等待(waiting)、时间等待(time waiting) 和 消亡(dead/terminated)。
+
+
+### 16 分页和分段有什么区别(内存管理)?
+* 段式存储管理是一种符合用户视角的内存分配管理方案。在段式存储管理中,将程序的地址空间划分为若干段(segment),如代码段,数据段,堆栈段;这样每个进程有一个二维地址空间,相互独立,互不干扰。段式管理的优点是:没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)。
+
+* 页式存储管理方案是一种用户视角内存与物理内存相分离的内存分配管理方案。在页式存储管理中,将程序的逻辑地址划分为固定大小的页(page),而物理内存划分为同样大小的帧,程序加载时,可以将任意一页放入内存中任意一个帧,这些帧不必连续,从而实现了离散分离。页式存储管理的优点是:没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满)。
+
+* 两者不同:
+ * 目的不同:分页是由于系统管理的需要而不是用户的需要,它是信息的物理单位;分段的目的是为了能更好地满足用户的需要,它是信息的逻辑单位,它含有一组其意义相对完整的信息;
+ * 大小不同:页的大小固定且由系统决定,而段的长度却不固定,由其所完成的功能决定;
+ * 地址空间不同:段向用户提供二维地址空间;页向用户提供的是一维地址空间;
+ * 信息共享:段是信息的逻辑单位,便于存储保护和信息的共享,页的保护和共享受到限制;
+ * 内存碎片:页式存储管理的优点是没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满);而段式管理的优点是没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)。
+
+### 17 操作系统中进程调度策略有哪几种?
+1. FCFS(先来先服务,队列实现,非抢占的):先请求CPU的进程先分配到CPU。
+2. SJF(最短作业优先调度算法):平均等待时间最短,但难以知道下一个CPU区间长度。
+3. 优先级调度算法:优先级越高越先分配到CPU,相同优先级先到先服务,存在的主要问题是:低优先级进程无穷等待CPU,会导致无穷阻塞或饥饿;解决方案:老化。
+4. 时间片轮转调度算法(可抢占的):队列中没有进程被分配超过一个时间片的CPU时间,除非它是唯一可运行的进程。如果进程的CPU区间超过了一个时间片,那么该进程就被抢占并放回就绪队列。
+5. 多级队列调度算法:将就绪队列分成多个独立的队列,每个队列都有自己的调度算法,队列之间采用固定优先级抢占调度。其中,一个进程根据自身属性被永久地分配到一个队列中。
+6. 多级反馈队列调度算法:与多级队列调度算法相比,其允许进程在队列之间移动:若进程使用过多CPU时间,那么它会被转移到更低的优先级队列;在较低优先级队列等待时间过长的进程会被转移到更高优先级队列,以防止饥饿发生。
+
+### 18 说一说进程同步有哪几种机制?
+
+* 原子操作、信号量机制、自旋锁管程、会合、分布式系统
+
+### 19 什么是虚拟内存?
+* 内存发展历程没有内存抽象(单进程,除去操作系统所用的内存之外,全部给用户程序使用) —>有内存抽象(多进程,进程独立的地址空间,交换技术(内存大小不可能容纳下所有并发执行的进程)—> 连续内存分配(固定大小分区(多道程序的程度受限),可变分区(首次适应,最佳适应,最差适应),碎片)—> 不连续内存分配(分段,分页,段页式,虚拟内存)
+
+* 虚拟内存。虚拟内存允许执行进程不必完全在内存中。虚拟内存的基本思想是:每个进程拥有独立的地址空间,这个空间被分为大小相等的多个块,称为页(Page),每个页都是一段连续的地址。这些页被映射到物理内存,但并不是所有的页都必须在内存中才能运行程序。当程序引用到一部分在物理内存中的地址空间时,由硬件立刻进行必要的映射;当程序引用到一部分不在物理内存中的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败的命令。这样,对于进程而言,逻辑上似乎有很大的内存空间,实际上其中一部分对应物理内存上的一块(称为帧,通常页和帧大小相等),还有一些没加载在内存中的对应在硬盘上,如图所示。
+
+* 由图可以看出,虚拟内存实际上可以比物理内存大。当访问虚拟内存时,会访问MMU(内存管理单元)去匹配对应的物理地址(比如图5的0,1,2)。如果虚拟内存的页并不存在于物理内存中(如图5的3,4),会产生缺页中断,从磁盘中取得缺的页放入内存,如果内存已满,还会根据某种算法将磁盘中的页换出。
+
+* 页面置换算法
+ * FIFO先进先出算法:在操作系统中经常被用到,比如作业调度(主要实现简单,很容易想到);
+ * LRU(Least recently use)最近最少使用算法:根据使用时间到现在的长短来判断;
+ * LFU(Least frequently use)最少使用次数算法:根据使用次数来判断;
+ * OPT(Optimal replacement)最优置换算法:理论的最优,理论;就是要保证置换出去的是不再被使用的页,或者是在实际内存中最晚使用的算法。
+
+* 虚拟内存应用及优点
+ * 虚拟内存很适合在多道程序设计系统中使用,许多程序的片段同时保存在内存中。当一个程序等待它的一部分读入内存时,可以把CPU交给另一个进程使用。好处:
+ * 在内存中可以保留多个进程,系统并发度提高。
+ * 解除了用户与内存之间的紧密约束,进程可以比内存的全部空间还大
+
+### 20 颠簸
+* 颠簸本质上是指频繁的页调度行为,具体来讲,进程发生缺页中断,这时,必须置换某一页。然而,其他所有的页都在使用,它置换一个页,但又立刻再次需要这个页。因此,会不断产生缺页中断,导致整个系统的效率急剧下降,这种现象称为颠簸(抖动)。
+* 解决策略包括:
+ * 如果是因为页面替换策略失误,可以修改替换算法来解决这个问题;
+ * 如果是因为运行的程序太多,造成程序无法同时将所有频繁访问的页面调入内存,则要降低多道程序的数量;
+ * 否则,还剩下两个办法:终止该进程或增加物理内存容量。
+
+### 21 局部性原理
+* 时间上的局部性:最近被访问的页在不久的将来还会被访问;
+* 空间上的局部性:内存中被访问的页周围的页也很可能被访问。
diff --git a/操作系统/附录3 Socket.md b/操作系统/附录3 Socket.md
new file mode 100644
index 00000000..2348ebfa
--- /dev/null
+++ b/操作系统/附录3 Socket.md
@@ -0,0 +1,337 @@
+# Socket
+
+* [Socket](#socket)
+ * [一、I/O 模型](#一io-模型)
+ * [阻塞式 I/O](#阻塞式-io)
+ * [非阻塞式 I/O](#非阻塞式-io)
+ * [I/O 复用](#io-复用)
+ * [信号驱动 I/O](#信号驱动-io)
+ * [异步 I/O](#异步-io)
+ * [五大 I/O 模型比较](#五大-io-模型比较)
+ * [二、I/O 复用](#二io-复用)
+ * [select](#select)
+ * [poll](#poll)
+ * [比较](#比较)
+ * [epoll](#epoll)
+ * [工作模式](#工作模式)
+ * [应用场景](#应用场景)
+ * [参考资料](#参考资料)
+
+
+
+## 一、I/O 模型
+
+一个输入操作通常包括两个阶段:
+
+- 等待数据准备好
+- 从内核向进程复制数据
+
+对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待数据到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。
+
+Unix 有五种 I/O 模型:
+
+- 阻塞式 I/O
+- 非阻塞式 I/O
+- I/O 复用(select 和 poll)
+- 信号驱动式 I/O(SIGIO)
+- 异步 I/O(AIO)
+
+### 阻塞式 I/O
+
+应用进程被阻塞,直到数据从内核缓冲区复制到应用进程缓冲区中才返回。
+
+应该注意到,在阻塞的过程中,其它应用进程还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其它应用进程还可以执行,所以不消耗 CPU 时间,这种模型的 CPU 利用率会比较高。
+
+下图中,recvfrom() 用于接收 Socket 传来的数据,并复制到应用进程的缓冲区 buf 中。这里把 recvfrom() 当成系统调用。
+
+```c
+ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
+```
+
+
+
+### 非阻塞式 I/O
+
+应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为轮询(polling)。
+
+由于 CPU 要处理更多的系统调用,因此这种模型的 CPU 利用率比较低。
+
+
+
+### I/O 复用
+
+使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读。这一过程会被阻塞,当某一个套接字可读时返回,之后再使用 recvfrom 把数据从内核复制到进程中。
+
+它可以让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O,即事件驱动 I/O。
+
+如果一个 Web 服务器没有 I/O 复用,那么每一个 Socket 连接都需要创建一个线程去处理。如果同时有几万个连接,那么就需要创建相同数量的线程。相比于多进程和多线程技术,I/O 复用不需要进程线程创建和切换的开销,系统开销更小。
+
+
+
+### 信号驱动 I/O
+
+应用进程使用 sigaction 系统调用,内核立即返回,应用进程可以继续执行,也就是说等待数据阶段应用进程是非阻塞的。内核在数据到达时向应用进程发送 SIGIO 信号,应用进程收到之后在信号处理程序中调用 recvfrom 将数据从内核复制到应用进程中。
+
+相比于非阻塞式 I/O 的轮询方式,信号驱动 I/O 的 CPU 利用率更高。
+
+
+
+### 异步 I/O
+
+应用进程执行 aio_read 系统调用会立即返回,应用进程可以继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。
+
+异步 I/O 与信号驱动 I/O 的区别在于,异步 I/O 的信号是通知应用进程 I/O 完成,而信号驱动 I/O 的信号是通知应用进程可以开始 I/O。
+
+
+
+### 五大 I/O 模型比较
+
+- 同步 I/O:将数据从内核缓冲区复制到应用进程缓冲区的阶段(第二阶段),应用进程会阻塞。
+- 异步 I/O:第二阶段应用进程不会阻塞。
+
+同步 I/O 包括阻塞式 I/O、非阻塞式 I/O、I/O 复用和信号驱动 I/O ,它们的主要区别在第一个阶段。
+
+非阻塞式 I/O 、信号驱动 I/O 和异步 I/O 在第一阶段不会阻塞。
+
+
+
+## 二、I/O 复用
+
+select/poll/epoll 都是 I/O 多路复用的具体实现,select 出现的最早,之后是 poll,再是 epoll。
+
+### select
+
+```c
+int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
+```
+
+select 允许应用程序监视一组文件描述符,等待一个或者多个描述符成为就绪状态,从而完成 I/O 操作。
+
+- fd_set 使用数组实现,数组大小使用 FD_SETSIZE 定义,所以只能监听少于 FD_SETSIZE 数量的描述符。有三种类型的描述符类型:readset、writeset、exceptset,分别对应读、写、异常条件的描述符集合。
+
+- timeout 为超时参数,调用 select 会一直阻塞直到有描述符的事件到达或者等待的时间超过 timeout。
+
+- 成功调用返回结果大于 0,出错返回结果为 -1,超时返回结果为 0。
+
+```c
+fd_set fd_in, fd_out;
+struct timeval tv;
+
+// Reset the sets
+FD_ZERO( &fd_in );
+FD_ZERO( &fd_out );
+
+// Monitor sock1 for input events
+FD_SET( sock1, &fd_in );
+
+// Monitor sock2 for output events
+FD_SET( sock2, &fd_out );
+
+// Find out which socket has the largest numeric value as select requires it
+int largest_sock = sock1 > sock2 ? sock1 : sock2;
+
+// Wait up to 10 seconds
+tv.tv_sec = 10;
+tv.tv_usec = 0;
+
+// Call the select
+int ret = select( largest_sock + 1, &fd_in, &fd_out, NULL, &tv );
+
+// Check if select actually succeed
+if ( ret == -1 )
+ // report error and abort
+else if ( ret == 0 )
+ // timeout; no event detected
+else
+{
+ if ( FD_ISSET( sock1, &fd_in ) )
+ // input event on sock1
+
+ if ( FD_ISSET( sock2, &fd_out ) )
+ // output event on sock2
+}
+```
+
+### poll
+
+```c
+int poll(struct pollfd *fds, unsigned int nfds, int timeout);
+```
+
+poll 的功能与 select 类似,也是等待一组描述符中的一个成为就绪状态。
+
+poll 中的描述符是 pollfd 类型的数组,pollfd 的定义如下:
+
+```c
+struct pollfd {
+ int fd; /* file descriptor */
+ short events; /* requested events */
+ short revents; /* returned events */
+ };
+```
+
+
+```c
+// The structure for two events
+struct pollfd fds[2];
+
+// Monitor sock1 for input
+fds[0].fd = sock1;
+fds[0].events = POLLIN;
+
+// Monitor sock2 for output
+fds[1].fd = sock2;
+fds[1].events = POLLOUT;
+
+// Wait 10 seconds
+int ret = poll( &fds, 2, 10000 );
+// Check if poll actually succeed
+if ( ret == -1 )
+ // report error and abort
+else if ( ret == 0 )
+ // timeout; no event detected
+else
+{
+ // If we detect the event, zero it out so we can reuse the structure
+ if ( fds[0].revents & POLLIN )
+ fds[0].revents = 0;
+ // input event on sock1
+
+ if ( fds[1].revents & POLLOUT )
+ fds[1].revents = 0;
+ // output event on sock2
+}
+```
+
+### 比较
+
+#### 1. 功能
+
+select 和 poll 的功能基本相同,不过在一些实现细节上有所不同。
+
+- select 会修改描述符,而 poll 不会;
+- select 的描述符类型使用数组实现,FD_SETSIZE 大小默认为 1024,因此默认只能监听少于 1024 个描述符。如果要监听更多描述符的话,需要修改 FD_SETSIZE 之后重新编译;而 poll 没有描述符数量的限制;
+- poll 提供了更多的事件类型,并且对描述符的重复利用上比 select 高。
+- 如果一个线程对某个描述符调用了 select 或者 poll,另一个线程关闭了该描述符,会导致调用结果不确定。
+
+#### 2. 速度
+
+select 和 poll 速度都比较慢,每次调用都需要将全部描述符从应用进程缓冲区复制到内核缓冲区。
+
+#### 3. 可移植性
+
+几乎所有的系统都支持 select,但是只有比较新的系统支持 poll。
+
+### epoll
+
+```c
+int epoll_create(int size);
+int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
+int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
+```
+
+epoll_ctl() 用于向内核注册新的描述符或者是改变某个文件描述符的状态。已注册的描述符在内核中会被维护在一棵红黑树上,通过回调函数内核会将 I/O 准备好的描述符加入到一个链表中管理,进程调用 epoll_wait() 便可以得到事件完成的描述符。
+
+从上面的描述可以看出,epoll 只需要将描述符从进程缓冲区向内核缓冲区拷贝一次,并且进程不需要通过轮询来获得事件完成的描述符。
+
+epoll 仅适用于 Linux OS。
+
+epoll 比 select 和 poll 更加灵活而且没有描述符数量限制。
+
+epoll 对多线程编程更有友好,一个线程调用了 epoll_wait() 另一个线程关闭了同一个描述符也不会产生像 select 和 poll 的不确定情况。
+
+```c
+// Create the epoll descriptor. Only one is needed per app, and is used to monitor all sockets.
+// The function argument is ignored (it was not before, but now it is), so put your favorite number here
+int pollingfd = epoll_create( 0xCAFE );
+
+if ( pollingfd < 0 )
+ // report error
+
+// Initialize the epoll structure in case more members are added in future
+struct epoll_event ev = { 0 };
+
+// Associate the connection class instance with the event. You can associate anything
+// you want, epoll does not use this information. We store a connection class pointer, pConnection1
+ev.data.ptr = pConnection1;
+
+// Monitor for input, and do not automatically rearm the descriptor after the event
+ev.events = EPOLLIN | EPOLLONESHOT;
+// Add the descriptor into the monitoring list. We can do it even if another thread is
+// waiting in epoll_wait - the descriptor will be properly added
+if ( epoll_ctl( epollfd, EPOLL_CTL_ADD, pConnection1->getSocket(), &ev ) != 0 )
+ // report error
+
+// Wait for up to 20 events (assuming we have added maybe 200 sockets before that it may happen)
+struct epoll_event pevents[ 20 ];
+
+// Wait for 10 seconds, and retrieve less than 20 epoll_event and store them into epoll_event array
+int ready = epoll_wait( pollingfd, pevents, 20, 10000 );
+// Check if epoll actually succeed
+if ( ret == -1 )
+ // report error and abort
+else if ( ret == 0 )
+ // timeout; no event detected
+else
+{
+ // Check if any events detected
+ for ( int i = 0; i < ready; i++ )
+ {
+ if ( pevents[i].events & EPOLLIN )
+ {
+ // Get back our connection pointer
+ Connection * c = (Connection*) pevents[i].data.ptr;
+ c->handleReadEvent();
+ }
+ }
+}
+```
+
+
+### 工作模式
+
+epoll 的描述符事件有两种触发模式:LT(level trigger)和 ET(edge trigger)。
+
+#### 1. LT 模式
+
+当 epoll_wait() 检测到描述符事件到达时,将此事件通知进程,进程可以不立即处理该事件,下次调用 epoll_wait() 会再次通知进程。是默认的一种模式,并且同时支持 Blocking 和 No-Blocking。
+
+#### 2. ET 模式
+
+和 LT 模式不同的是,通知之后进程必须立即处理事件,下次再调用 epoll_wait() 时不会再得到事件到达的通知。
+
+很大程度上减少了 epoll 事件被重复触发的次数,因此效率要比 LT 模式高。只支持 No-Blocking,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。
+
+### 应用场景
+
+很容易产生一种错觉认为只要用 epoll 就可以了,select 和 poll 都已经过时了,其实它们都有各自的使用场景。
+
+#### 1. select 应用场景
+
+select 的 timeout 参数精度为微秒,而 poll 和 epoll 为毫秒,因此 select 更加适用于实时性要求比较高的场景,比如核反应堆的控制。
+
+select 可移植性更好,几乎被所有主流平台所支持。
+
+#### 2. poll 应用场景
+
+poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select。
+
+#### 3. epoll 应用场景
+
+只需要运行在 Linux 平台上,有大量的描述符需要同时轮询,并且这些连接最好是长连接。
+
+需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势。
+
+需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且 epoll 的描述符存储在内核,不容易调试。
+
+## 参考资料
+
+- Stevens W R, Fenner B, Rudoff A M. UNIX network programming[M]. Addison-Wesley Professional, 2004.
+- http://man7.org/linux/man-pages/man2/select.2.html
+- http://man7.org/linux/man-pages/man2/poll.2.html
+- [Boost application performance using asynchronous I/O](https://www.ibm.com/developerworks/linux/library/l-async/)
+- [Synchronous and Asynchronous I/O](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365683(v=vs.85).aspx)
+- [Linux IO 模式及 select、poll、epoll 详解](https://segmentfault.com/a/1190000003063859)
+- [poll vs select vs event-based](https://daniel.haxx.se/docs/poll-vs-select.html)
+- [select / poll / epoll: practical difference for system architects](http://www.ulduzsoft.com/2014/01/select-poll-epoll-practical-difference-for-system-architects/)
+- [Browse the source code of userspace/glibc/sysdeps/unix/sysv/linux/ online](https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/)
diff --git a/操作系统/附录4 寄存器.md b/操作系统/附录4 寄存器.md
new file mode 100644
index 00000000..f19a7273
--- /dev/null
+++ b/操作系统/附录4 寄存器.md
@@ -0,0 +1,32 @@
+## 寄存器
+
+### 定义
+
+* PSW是Program Status Word的缩写,即程序状态字(也叫程序状态寄存器),可用于OS在管态(系统态)和目态(用户态)之间的转换。
+* 程序状态寄存器PSW是计算机系统的核心部件——运算器的一部分,PSW用来存放两类信息:一类是体现当前指令执行结果的各种状态信息,称为状态标志,如有无借位进位(CY位)、有无溢出(OF位)、结果正负(SF位)、结果是否为零(ZF位)、奇偶标志位(PF位)等;另一类是存放控制信息,称为控制状态,如允许中断(IF位),跟踪标志(TF位),方向标志(DF)等。
+
+### 使用
+* 程序状态字用来指示处理器状态、控制指令的执行顺序并且保留和指示与运行程序有关的各种信息,其主要作用是方便地实现程序状态的保护和恢复。每个正在执行的程序都有一个与其执行相关的PSW,而每个处理器都设置一个程序状态字寄存器。一个程序占有处理器执行,它的PSW将占有程序状态字寄存器。一般来说,程序状态字寄存器包括以下几类内容:
+
+* 程序基本状态。包括:(1)程序计数器:指明下一条执行的指令地址;(2)条件码:表示指令执行的结果状态:(3)处理器状态位:指明当前的处理器状态,如目态或管态、运行或等待。
+ * 中断码。保存程序执行时当前发生的中断事件。
+ * 中断屏蔽位。指明程序执行中发生中断事件时,是否响应出现的中断事件。
+* 由于不同处理器中的控制寄存器组织方式不同,所以在大多数计算机的处理器现场中可能找不到一个称为程序状态字寄存器的具体寄存器,但总是有一组控制与状态寄存器实际上起到这一作用。
+
+
+## 进程通信
+
+### 进程通信的类型
+* 共享存储器系统
+ * 基于共享数据结构的通信方式
+ * 生产者和消费者
+* 基于共享存储区的通信方式
+ * 高级通信
+* 管道通信系统(pipe)
+ * 高级通信
+* 消息传递系统
+ * 高级通信
+ * 方式分类
+ * 直接通信
+ * 间接通信
+* 客服机–服务器系统
\ No newline at end of file
diff --git a/数据结构/6.8 堆树.md b/数据结构/6.8 堆树.md
index 9f31743c..dabc0aba 100644
--- a/数据结构/6.8 堆树.md
+++ b/数据结构/6.8 堆树.md
@@ -10,7 +10,9 @@
1. 堆是一颗完全二叉树;
2. 堆中的某个结点的值总是大于等于(最大堆)或小于等于(最小堆)其孩子结点的值。
-3. 堆中每个结点的子树都是堆树
+3. 堆中每个结点的子树都是堆树。
+
+> 因为堆的第三条性质,堆的每一个子树,都是一个堆树。如果从叶节点开始进行一次向上调整。虽然能够保证最大值上浮到根节点。但是却无法保证它是一个堆树。因为进行一次向上调整。根节点的子树也许不是堆树。

@@ -74,7 +76,7 @@
> 类似于冒泡的思想,但是是一中更快的冒泡。保证最后能够建立最好的堆。
-* 从根节点向叶节点开始,从后往前开始。进行多次上浮操作。
+* 从根节点向叶节点开始,从前往后开始。进行多次上浮操作。
* 从叶节点向根节点开始,从后往前开始。进行多次下沉操作。
diff --git a/算法/A类:基本算法/1 算法概述.md b/算法/A类:基本算法/1 算法概述.md
index dd2426d3..875458c4 100644
--- a/算法/A类:基本算法/1 算法概述.md
+++ b/算法/A类:基本算法/1 算法概述.md
@@ -143,3 +143,87 @@
|贪心算法|最优子结构性质;贪心选择性质。|
|回溯法|多米诺性质(叶子节点的解一定满足其父节点)。|
|分支限界|多米诺性质;求解最优解或一个可行解。|
+
+## 5 简单对比
+## 5.1 暴力破解法(Brute Force Paradigm)
+* 暴力破解法简单直接,根据问题声明的定义,找到所有可变化的因子(Divisor),穷举所有可能解决问题的方法,逐个尝试。所以,根据暴力破解法的定义,理论上讲任何问题都可以使用暴力破解法来解决,只是在实际应用中算法对时间和空间的需求则无法满足。将暴力破解法应用于数据查找,由于查找比较次数与给定目标的规模直接相关,所以也称为线性查找(Linear Search)。
+
+### 线性查找有很多典型应用:
+* 选择排序(Selection Sort)
+* 冒泡排序(Bubble Sort)
+* 顺序查找(Sequential Search)
+* 暴力字符串匹配(Naive String Match)
+
+## 5.3 分治法(Divide and Conquer Paradigm)
+* 分治法(Divide-and-Conquer),即 "分而治之",是将原问题划分成 n 个规模较小而结构与原问题相似的子问题,递归地解决这些问题,然后再合并其结果,以得到原问题的解。
+* 当我们遇到一个大问题时,总是习惯把问题的规模变小,这样便于分析讨论。这些规模变小后的问题和原来的问题是同质的,除了规模变小,其它的都是一样的,本质上它还是同一个问题,规模变小后的问题其实是原问题的子问题。
+
+### 分治模式在每一层上都有三个步骤:
+* 分解(Divide):将原问题分解成一系列与原问题同质的子问题;
+* 解决(Conquer):递归地解决各个子问题。若子问题足够小,则直接求解;
+* 合并(Combine):将子问题的结果合并成原问题的解。
+
+### 分治法所能解决的问题一般具有以下几个特征:
+* 可以将问题分解为若干个规模较小的相同问题;
+* 问题的规模缩小到一定程度后就可以很容易地解决;
+* 问题分解出的子问题的解可以合并为该问题的解;
+* 问题所分解出的各个子问题是相互独立的,即子问题之间不再包含公共的孙问题。
+> 符合 1,2,3 条特征是使用分治法的关键,而特征 4 将涉及到分治法的效率问题。而如果不符合 3,4 特征的问题可以尝试考虑使用动态规划或贪心算法来解决。
+### 分治法的典型应用:
+* 合并排序(Merge Sort)
+* 快速排序(Quick Sort)
+* 二分查找(Binary Search)
+## 5.3 动态规划法(Dynamic Programming Paradigm)
+* 动态规划的过程可以描述为多阶段最优化解决问题的过程,每一次的决策依赖于当前的状态,随即又引起状态的转移,以此类推在变化的状态中产生出决策序列。
+* 动态规划算法通常基于一个递推公式及一个或多个初始状态,当前子问题的解将由上一次子问题的解推出。使用动态规划来解题通常只需要多项式时间复杂度,所以会比回溯法、暴力法等要快许多。
+
+### 动态规划方法中的关键词包括:
+* 阶段(Stage)、
+* 状态(State)、
+* 决策(Decision)、
+* 递推关系(Recurrent Relation)。
+
+### 动态规划对比
+* 动态规划首先将待求解的问题分解为若干个子问题(阶段),按顺序求解子问题。前一子问题的解为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。以此类推解决各子问题,最后一个子问题的解就是初始问题的解。
+* 动态规划与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子问题的求解是建立在上一个子问题的解的基础上,进行进一步的求解)。
+
+### 动态规划所能解决的问题一般具有以下几个特征:
+* 最优化原理(Mathematical Optimization):如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构(Optimal Substructure),即满足最优化原理。
+* 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。
+* 有重叠子问题(Overlapping Subproblems):即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。
+
+> 特征 3 并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势。
+
+### 动态规划的基本步骤:
+* 划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。
+* 确定状态和状态变量:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。状态的选择要满足无后效性。
+* 确定决策并写出状态转移方程:因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以如果确定了决策,状态转移方程也就可写出。但事实上常常是反过来做,根据相邻两个阶段的状态之间的关系来确定决策方法和状态转移方程。
+* 寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。
+
+
+## 5.4 贪心算法(Greedy Paradigm)
+* 所谓贪心算法是指,在对问题求解时,总是做出在当前看来最好的选择。也就是说,不从整体最优上加以考虑,它所做出的仅是在某种意义上的局部最优解。
+* 贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。贪心策略适用的前提是:局部最优策略能导致产生全局最优解。所以实际上,贪心算法适用的情况很少。
+* 贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。所以对所采用的贪心策略一定要仔细分析其是否满足无后效性。
+
+### 贪心算法的基本思路:
+* 建立数学模型来描述问题。
+* 把求解的问题分成若干个子问题。
+* 对每一子问题求解,得到子问题的局部最优解。
+* 把子问题的解局部最优解合成原来问题的一个解。
+
+## 5.5 回溯法(Backtracking Paradigm)
+* 回溯法描述了一种选优搜索过程,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先的选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的方法称为回溯法,而满足回溯条件的某个状态的点称为 "回溯点"。
+* 回溯法可以理解为隐式的深度优先搜索算法。其在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根节点出发深度探索解空间树。当探索到某一节点时,要先判断该节点是否包含问题的解,如果包含,就从该节点出发继续探索下去,如果该节点不包含问题的解,则逐层向其祖先节点回溯。
+* 许多复杂的,规模较大的问题都可以使用回溯法,有 "通用解题方法" 的美称。
+
+### 回溯法的一般步骤:
+* 针对给定问题,确定问题的解空间,问题的解空间应至少包含问题的一个(最优)解;
+* 确定节点的扩展搜索规则;
+* 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索;
+
+## 5.6 分支限界法(Branch and Bound Paradigm)
+* 类似于回溯法,分支限界法也是一种在问题的解空间树上搜索问题解的算法。但在一般情况下,分支限界法与回溯法的求解目标不同。回溯法的求解目标是找出树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数值达到极大或极小的解,即在某种意义下的最优解。
+* 所谓 "分支" 就是采用广度优先搜索算法,依次搜索节点的所有分支,抛弃不满足约束条件的节点,然后从余下的节点中选择一个节点作为下一个搜索节点继续搜索。
+* 由于求解目标不同,导致分支限界法与回溯法在解空间树上的搜索方式也不相同。回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。
+* 分支限界法的搜索策略是:在扩展节点处,先生成其所有的儿子节点(分支),然后再从当前的活节点表中选择下一个扩展节点。为了有效地选择下一扩展节点,以加速搜索的进程,在每一活节点处,计算一个函数值(限界),并根据这些已计算出的函数值,从当前活节点表中选择一个最有利的节点作为扩展节点,使搜索朝着解空间树上有最优解的分支推进,以便尽快地找出一个最优解。
\ No newline at end of file
diff --git a/算法/A类:基本算法/11 递归与迭代.md b/算法/A类:基本算法/11 递归与迭代.md
index 7abf1555..63de4b70 100644
--- a/算法/A类:基本算法/11 递归与迭代.md
+++ b/算法/A类:基本算法/11 递归与迭代.md
@@ -70,6 +70,9 @@ T(n)=\begin{cases}
\end{cases}
$$
+### 递归的空间复杂度
+* 当递归过深时,栈空间会被耗尽,这时就无法开辟新的函数,会报出stack overflow这样的错误。
+* 所以,在考虑空间复杂度时,递归函数的深度也是要考虑进去的。
## 2 递归的分类
### 直接递归和间接递归
* 直接递归,是指函数自己调用自己的情况。
diff --git a/算法/A类:基本算法/3 蛮力法(枚举法).md b/算法/A类:基本算法/3 蛮力法(枚举法).md
index 82fa7ab5..02d7a9d7 100644
--- a/算法/A类:基本算法/3 蛮力法(枚举法).md
+++ b/算法/A类:基本算法/3 蛮力法(枚举法).md
@@ -1,102 +1,13 @@
# 蛮力法
-## 1 蛮力法概述
+## 0 蛮力法概述
* 蛮力法是一种简单直接地解决问题的方法,常常直接 基于问题的描述和所涉及的概念定义。
-## 2 排序问题
-(主要描述解决问题的步骤)
-### 理解问题
-* 问题:给定一个可排序的n个元素序列(数字、字符或字符串),对它们按照非降序方式重新排列。
-
-### 选择策略
-* 思想:首先扫描整个序列,找到其中一个最小元素,然后和第一个元素交换,将最小元素归位。然后从第二个元素开始扫描序列,找到后n-1个元素中的一个最小元素,然后和第二个元素交换,将第二小元素归位。进行n-1遍扫描之后,排序完成。
-### 算法设计
-
-* 算法 selectSort(A[n])
-```
-//用选择法对给定数组排序
-//输入:一个可排序数组A[0..n-1]
-//输出:升序排序的数组A[0..n-1]
-for i←0 to n-2 do
- min←i
- for j=i+1 to n-1 do
- if A[j] < A[min] min←j
- swap A[i] and A[min]
-```
-### 正确性证明
-
-### 算法分析
-* 输入规模:序列元素个数n
-* 基本操作:比较次数A[j] < A[min]
-* 影响操作执行的其他因素:n
-* 构建基本操作的求和表达式:利用求和公式分析算法的时间复杂度:
-
-
-### 程序设计
-
-## 3 顺序查找问题
-(主要是分析解决问题的步骤)
-### 理解问题
-* 思想:查找键与表中元素从头至尾逐个比较。
-* 结果:找到 或 失败
-* 限位器:把查找键添加到列表末尾—— 一定成功,避免每次循环时对检查是否越界(边界检查)
-* 选择策略
-
-### 算法设计
-
-
-
-
-### 正确性证明
-
-### 算法分析
-* 最佳效率:Tbest (n) = 1
-* 最差效率:Tworst(n) = n + 1
-* 问:为何定义 A 数组为 n+1 维?答:有一个位置放限位器
-* 问:若输入有序,算法可改进?答:遇到 ≤ 或 ≥ 查找键元素,立即停止查找。
-
-### 程序设计
-
-
-## 4 字符串匹配问题
-### 理解问题
-* 问题:给定一个n个字符组成的串,称为文本,一个m(m≤n)个字符组成的串称为模式,从文本中寻找匹配模式的子串。
-### 选择策略
-* 思想:将模式对准文本的前m个字符,然后从左到右匹配每一对相应的字符,若遇到一对不匹配字符,模式向右移一位,重新开始匹配;若m对字符全部匹配,算法可以停止。注意,在文本中,最后一轮子串匹配的起始位置是n-m(假设文本的下标从0到n-1)
-### 算法设计
-* 算法 bruteForceStringMatch(T[0..n-1],P[0..m-1])
-```
-//蛮力字符串匹配算法实现
-//输入1:一个n个字符的数组T[0..n-1]代表一段文本
-//输入2:一个m个字符的数组P[0..m-1]代表一个模式
-//输出:若查找成功,返回文本第一个匹配子串中的第一个字符的位置,否则返回-1
-for i←0 to n-m do
- j←0
- while j unsorted[j + 1])
-24 {
-25 int temp = unsorted[j];
-26 unsorted[j] = unsorted[j + 1];
-27 unsorted[j + 1] = temp;
-28 }
-29 }
-30 }
-31 }
-32
-33 static void OptimizedBubbleSort(int[] unsorted)
-34 {
-35 int exchange = unsorted.Length - 1;
-36 while (exchange > 0)
-37 {
-38 int lastExchange = exchange;
-39 exchange = 0;
-40
-41 for (int i = 0; i < lastExchange; i++)
-42 {
-43 if (unsorted[i] > unsorted[i + 1])
-44 {
-45 int temp = unsorted[i];
-46 unsorted[i] = unsorted[i + 1];
-47 unsorted[i + 1] = temp;
-48
-49 exchange = i;
-50 }
-51 }
-52 }
-53 }
-54 }
+```C++
+vector bubble_sort(vector vec){
+ for(int i=0;ivec[j+1]){
+ swap(vec[j],vec[j+1]);
+ }
+ }
+ }
+ return vec;
+}
```
## 2 鸡尾酒排序(Cocktail Sort)
@@ -615,299 +571,33 @@ RANDOMIZED-QUICKSORT 的平均运行情况是 O(n lg n),如果在递归的每
快速排序也会与合并排序(Merge Sort)竞争。合并排序的特点是最坏情况有着 O(n log n) 运行时间的优势。不像快速排序或堆排序,合并排序是一个稳定排序算法,并且非常的灵活,其设计可以应用于操作链表,或大型链式存储等,例如磁盘存储或网路附加存储等。尽管快速排序也可以被重写使用在链表上,但对于基准的选择总是个问题。合并排序的主要缺点是在最佳情况下需要 O(n) 额外的空间,而快速排序的原地分区和尾部递归仅使用 O(log n) 的空间。
### 代码示例
-```
- 1 class Program
- 2 {
- 3 static bool isPrintArrayEnabled = false;
- 4
- 5 static void Main(string[] args)
- 6 {
- 7 int[] smallSeed = { 4, 1, 5, 2, 6, 3, 7, 9, 8, 0 };
- 8
- 9 MeasureQuickSort(smallSeed, 1000000);
- 10 MeasureRandomizedQuickSort(smallSeed, 1000000);
- 11 MeasureOptimizedQuickSorts(smallSeed, 1000000);
- 12
- 13 Console.Read();
- 14 }
- 15
- 16 static void MeasureQuickSort(int[] smallSeed, int arrayLength)
- 17 {
- 18 int[] unsorted = GenerateBigUnsortedArray(smallSeed, arrayLength);
- 19
- 20 Stopwatch watch = Stopwatch.StartNew();
- 21
- 22 QuickSort(unsorted, 0, unsorted.Length - 1);
- 23
- 24 watch.Stop();
- 25
- 26 Console.WriteLine(
- 27 "ArrayLength[{0}], QuickSort ElapsedMilliseconds[{1}]",
- 28 unsorted.Length, watch.ElapsedMilliseconds);
- 29
- 30 PrintArray(unsorted);
- 31 }
- 32
- 33 static void MeasureRandomizedQuickSort(int[] smallSeed, int arrayLength)
- 34 {
- 35 int[] unsorted = GenerateBigUnsortedArray(smallSeed, arrayLength);
- 36
- 37 Stopwatch watch = Stopwatch.StartNew();
- 38
- 39 RandomizedQuickSort(unsorted, 0, unsorted.Length - 1);
- 40
- 41 watch.Stop();
- 42
- 43 Console.WriteLine(
- 44 "ArrayLength[{0}], RandomizedQuickSort ElapsedMilliseconds[{1}]",
- 45 unsorted.Length, watch.ElapsedMilliseconds);
- 46
- 47 PrintArray(unsorted);
- 48 }
- 49
- 50 static void QuickSort(int[] unsorted, int left, int right)
- 51 {
- 52 // left 为子数列的最左边元素
- 53 // right 为子数列的最右边元素
- 54 if (!(left < right)) return;
- 55
- 56 // Partition:
- 57 // 所有元素比主元值小的摆放在主元的左边,
- 58 // 所有元素比主元值大的摆放在主元的右边
- 59 int pivotIndex = Partition(unsorted, left, right);
- 60
- 61 // Recursively:
- 62 // 分别排列小于主元的值和大于主元的值的子数列
- 63 // 主元无需参加下一次排序
- 64 QuickSort(unsorted, left, pivotIndex - 1);
- 65 QuickSort(unsorted, pivotIndex + 1, right);
- 66 }
- 67
- 68 static int Partition(int[] unsorted, int left, int right)
- 69 {
- 70 int pivotIndex = right;
- 71
- 72 // 哨兵
- 73 int sentinel = unsorted[right];
- 74
- 75 // 子数组长度为 right - left + 1
- 76 int i = left - 1;
- 77 for (int j = left; j <= right - 1; j++)
- 78 {
- 79 if (unsorted[j] <= sentinel)
- 80 {
- 81 i++;
- 82 Swap(unsorted, i, j);
- 83 }
- 84 }
- 85
- 86 Swap(unsorted, i + 1, pivotIndex);
- 87
- 88 return i + 1;
- 89 }
- 90
- 91 static void RandomizedQuickSort(int[] unsorted, int left, int right)
- 92 {
- 93 // left 为子数列的最左边元素
- 94 // right 为子数列的最右边元素
- 95 if (!(left < right)) return;
- 96
- 97 // Partition:
- 98 // 所有元素比主元值小的摆放在主元的左边,
- 99 // 所有元素比主元值大的摆放在主元的右边
-100 int pivotIndex = RandomizedPartition(unsorted, left, right);
-101
-102 // Recursively:
-103 // 分别排列小于主元的值和大于主元的值的子数列
-104 // 主元无需参加下一次排序
-105 RandomizedQuickSort(unsorted, left, pivotIndex - 1);
-106 RandomizedQuickSort(unsorted, pivotIndex + 1, right);
-107 }
-108
-109 static int RandomizedPartition(int[] unsorted, int left, int right)
-110 {
-111 int i = random.Next(left, right);
-112 Swap(unsorted, i, right);
-113 return Partition(unsorted, left, right);
-114 }
-115
-116 static void Swap(int[] unsorted, int i, int j)
-117 {
-118 int temp = unsorted[i];
-119 unsorted[i] = unsorted[j];
-120 unsorted[j] = temp;
-121 }
-122
-123 static void MeasureOptimizedQuickSorts(int[] smallSeed, int arrayLength)
-124 {
-125 foreach (var pivotSelection in
-126 Enum.GetValues(typeof(QuickSortPivotSelectionType)))
-127 {
-128 int[] unsorted = GenerateBigUnsortedArray(smallSeed, arrayLength);
-129
-130 Stopwatch watch = Stopwatch.StartNew();
-131
-132 OptimizedQuickSort(unsorted, 0, unsorted.Length - 1,
-133 (QuickSortPivotSelectionType)pivotSelection);
-134
-135 watch.Stop();
-136
-137 Console.WriteLine(
-138 "ArrayLength[{0}], "
-139 + "QuickSortPivotSelectionType[{1}], "
-140 + "ElapsedMilliseconds[{2}]",
-141 unsorted.Length,
-142 (QuickSortPivotSelectionType)pivotSelection,
-143 watch.ElapsedMilliseconds);
-144
-145 PrintArray(unsorted);
-146 }
-147 }
-148
-149 static int[] GenerateBigUnsortedArray(int[] smallSeed, int arrayLength)
-150 {
-151 int[] bigSeed = new int[100];
-152 for (int i = 0; i < bigSeed.Length; i++)
-153 {
-154 bigSeed[i] =
-155 smallSeed[i % smallSeed.Length]
-156 + i / smallSeed.Length * 10;
-157 }
-158
-159 int[] unsorted = new int[arrayLength];
-160 for (int i = 0; i < unsorted.Length / bigSeed.Length; i++)
-161 {
-162 Array.Copy(bigSeed, 0, unsorted, i * bigSeed.Length, bigSeed.Length);
-163 }
-164
-165 return unsorted;
-166 }
-167
-168 static void OptimizedQuickSort(int[] unsorted, int left, int right,
-169 QuickSortPivotSelectionType pivotSelection)
-170 {
-171 // left 为子数列的最左边元素
-172 // right 为子数列的最右边元素
-173 if (!(left < right)) return;
-174
-175 // Partition:
-176 // 所有元素比主元值小的摆放在主元的左边,
-177 // 所有元素比主元值大的摆放在主元的右边
-178 Tuple pivotPair =
-179 OptimizedPartition(unsorted, left, right, pivotSelection);
-180
-181 // Recursively:
-182 // 分别排列小于主元的值和大于主元的值的子数列
-183 // 主元无需参加下一次排序
-184 OptimizedQuickSort(unsorted, left, pivotPair.Item1 - 1, pivotSelection);
-185 OptimizedQuickSort(unsorted, pivotPair.Item2 + 1, right, pivotSelection);
-186 }
-187
-188 static Tuple OptimizedPartition(
-189 int[] unsorted, int left, int right,
-190 QuickSortPivotSelectionType pivotSelection)
-191 {
-192 int pivotIndex = SelectPivot(unsorted, left, right, pivotSelection);
-193 int sentinel = unsorted[pivotIndex];
-194
-195 // 子数组长度为 right - left + 1
-196 int i = left - 1;
-197 int j = right + 1;
-198 while (true)
-199 {
-200 while (unsorted[++i] < sentinel) ;
-201 while (unsorted[--j] > sentinel) ;
-202 if (i >= j) break;
-203
-204 // 在主元左侧找到一个大于主元值的位置 i,
-205 // 在主元右侧找到一个小于主元值的位置 j,
-206 // 交换两个值
-207 Swap(unsorted, i, j);
-208 }
-209
-210 return new Tuple(i, j);
-211 }
-212
-213 static int SelectPivot(int[] unsorted, int left, int right,
-214 QuickSortPivotSelectionType pivotSelection)
-215 {
-216 switch (pivotSelection)
-217 {
-218 case QuickSortPivotSelectionType.FirstAsPivot:
-219 return left;
-220 case QuickSortPivotSelectionType.MiddleAsPivot:
-221 return (left + right) / 2;
-222 case QuickSortPivotSelectionType.LastAsPivot:
-223 return right;
-224 case QuickSortPivotSelectionType.RandomizedPivot:
-225 {
-226 // 在区间内随机选择位置
-227 if (right - left > 1)
-228 {
-229 return random.Next(left, right);
-230 }
-231 else
-232 {
-233 return left;
-234 }
-235 }
-236 case QuickSortPivotSelectionType.BalancedPivot:
-237 {
-238 // 选择起始、中间和结尾位置中的中位数
-239 int leftValue = unsorted[left];
-240 int middleValue = unsorted[(left + right) / 2];
-241 int rightValue = unsorted[right];
-242
-243 if (leftValue < middleValue)
-244 {
-245 if (middleValue < rightValue)
-246 {
-247 return (left + right) / 2;
-248 }
-249 else
-250 {
-251 return right;
-252 }
-253 }
-254 else
-255 {
-256 if (leftValue < rightValue)
-257 {
-258 return left;
-259 }
-260 else
-261 {
-262 return right;
-263 }
-264 }
-265 }
-266 }
-267
-268 return (left + right) / 2;
-269 }
-270
-271 static void PrintArray(int[] unsorted)
-272 {
-273 if (!isPrintArrayEnabled) return;
-274
-275 foreach (var item in unsorted)
-276 {
-277 Console.Write("{0} ", item);
-278 }
-279 Console.WriteLine();
-280 }
-281
-282 static Random random = new Random(new Guid().GetHashCode());
-283
-284 enum QuickSortPivotSelectionType
-285 {
-286 FirstAsPivot,
-287 MiddleAsPivot,
-288 LastAsPivot,
-289 RandomizedPivot,
-290 BalancedPivot,
-291 }
-292 }
+```C++
+// 快速排序
+int partion(vector&vec, int left, int right){
+ int index = right;
+ // 哨兵
+ int sentinel = vec[index];
+ // 子数组长度为 right - left + 1
+ int i = left;
+ // 从左到右,小的与前边交换。大的就会到右边。
+ for (int j = left; j <= right - 1; j++)
+ {
+ if (vec[j] <= sentinel)
+ {
+ swap(vec[i],vec[j]);
+ i++;
+ }
+ }
+ swap(vec[i],vec[index]);
+ return i;
+}
+vector quick_sort(vector &vec,int left,int right){
+ if(left>=right)return;
+ int index = partion(vec,left,right);
+ quick_sort(vec,left,index-1);
+ quick_sort(vec,index+1,right);
+ return vec;
+}
```
@@ -929,54 +619,21 @@ RANDOMIZED-QUICKSORT 的平均运行情况是 O(n lg n),如果在递归的每
* 最差空间复杂度 О(n),辅助空间 O(1)
### 代码示例
-```
- 1 class Program
- 2 {
- 3 static void Main(string[] args)
- 4 {
- 5 int[] unsorted = { 4, 1, 5, 2, 6, 3, 7, 9, 8 };
- 6
- 7 SelectionSort(unsorted);
- 8
- 9 foreach (var key in unsorted)
-10 {
-11 Console.Write("{0} ", key);
-12 }
-13
-14 Console.Read();
-15 }
-16
-17 static void SelectionSort(int[] unsorted)
-18 {
-19 // advance the position through the entire array
-20 // could do i < n-1 because single element is also min element
-21 for (int i = 0; i < unsorted.Length - 1; i++)
-22 {
-23 // find the min element in the unsorted a[i .. n-1]
-24 // assume the min is the first element
-25 int min = i;
-26
-27 // test against elements after i to find the smallest
-28 for (int j = i + 1; j < unsorted.Length; j++)
-29 {
-30 // if this element is less, then it is the new minimum
-31 if (unsorted[j] < unsorted[min])
-32 {
-33 // found new minimum, remember its index
-34 min = j;
-35 }
-36 }
-37
-38 // swap
-39 if (min != i)
-40 {
-41 int temp = unsorted[i];
-42 unsorted[i] = unsorted[min];
-43 unsorted[min] = temp;
-44 }
-45 }
-46 }
-47 }
+```C++
+vector selection_sort(vector vec){
+ int min=INT_MAX,min_index=0;
+ int i=0,j=0;
+ for(i=0;i unsorted[i])
-22 {
-23 int key = unsorted[i];
-24 int j = i;
-25 while (j > 0 && unsorted[j - 1] > key)
-26 {
-27 unsorted[j] = unsorted[j - 1];
-28 j--;
-29 }
-30 unsorted[j] = key;
-31 }
-32 }
-33 }
-34 }
+```C++
+vector insertion_sort(vector vec){
+ for(int i=1;i0;j--){
+ if(vec[j-1]>temp){
+ vec[j]=vec[j-1];
+ }
+ else{
+ break;
+ }
+ }
+ vec[j]=temp;
+ }
+ return vec;
+}
```
## 7 希尔排序(Shell Sort)
@@ -1147,75 +786,39 @@ RANDOMIZED-QUICKSORT 的平均运行情况是 O(n lg n),如果在递归的每
* 合并排序有着较好的渐进运行时间 Θ(nlogn),但其中的 merge 操作不是 in-place 操作。
### 示例代码
-```
- 1 class Program
- 2 {
- 3 static void Main(string[] args)
- 4 {
- 5 int[] unsorted = { 4, 1, 5, 2, 6, 3, 7, 9, 8 };
- 6
- 7 int[] temp = new int[unsorted.Length];
- 8 MergeSort(unsorted, 0, unsorted.Length, temp);
- 9 foreach (var key in unsorted)
-10 {
-11 Console.Write("{0} ", key);
-12 }
-13
-14 Console.Read();
-15 }
-16
-17 static void MergeSort(int[] unsorted, int left, int right, int[] temp)
-18 {
-19 if (left + 1 < right)
-20 {
-21 // divide
-22 int mid = (left + right) / 2;
-23
-24 // conquer
-25 MergeSort(unsorted, left, mid, temp);
-26 MergeSort(unsorted, mid, right, temp);
-27
-28 // combine
-29 Merge(unsorted, left, mid, right, temp);
-30 }
-31 }
-32
-33 static void Merge(int[] unsorted, int left, int mid, int right, int[] temp)
-34 {
-35 int leftPosition = left;
-36 int rightPosition = mid;
-37 int numberOfElements = 0;
-38
-39 // merge two slots
-40 while (leftPosition < mid && rightPosition < right)
-41 {
-42 if (unsorted[leftPosition] < unsorted[rightPosition])
-43 {
-44 temp[numberOfElements++] = unsorted[leftPosition++];
-45 }
-46 else
-47 {
-48 temp[numberOfElements++] = unsorted[rightPosition++];
-49 }
-50 }
-51
-52 // add remaining
-53 while (leftPosition < mid)
-54 {
-55 temp[numberOfElements++] = unsorted[leftPosition++];
-56 }
-57 while (rightPosition < right)
-58 {
-59 temp[numberOfElements++] = unsorted[rightPosition++];
-60 }
-61
-62 // copy back
-63 for (int n = 0; n < numberOfElements; n++)
-64 {
-65 unsorted[left + n] = temp[n];
-66 }
-67 }
-68 }
+```C++
+// 归并排序
+void merge(vector &vec,int left,int right,int mid){
+ vector temp(vec);
+ int left_index=left;
+ int right_index = mid+1;
+ int i=left;
+ while(left_index<=mid && right_index<=right){
+ if(temp[left_index]<=temp[right_index]){
+ vec[i++]=temp[left_index++];
+ }
+ else{
+ vec[i++]=temp[right_index++];
+ }
+ }
+ // 处理左边没有用完的数据。(右边没有用完的可以保留在原地
+ while(left_index<=mid){
+ vec[i++]=temp[left_index++];
+ }
+ return;
+}
+// 头递归
+void merge_sort(vector &vec,int left,int right){
+ if(left>=right)return;
+ // divide
+ int mid = (left+right)/2;
+ // conquer
+ merge_sort(vec,left,mid);
+ merge_sort(vec,mid+1,right);
+ // combine
+ merge(vec,left,right,mid);
+ return;
+}
```
## 9 堆排序(Heap Sort)
@@ -1226,7 +829,7 @@ RANDOMIZED-QUICKSORT 的平均运行情况是 O(n lg n),如果在递归的每
二叉堆有两种,最大堆和最小堆。最大堆特性是指除了根以外的每个节点 i ,有 A(Parent(i)) ≥ A[i] ,即某个节点的值至多是和其父节点的值一样大。最小堆特性是指除了根以外的每个节点 i ,有 A(Parent(i)) ≤ A[i] ,最小堆的最小元素在根部。
-在堆排序算法中,我们使用的是最大堆。最小堆通常在构造有限队列时使用。
+在堆排序算法中,我们使用的是最大堆。最小堆通常在构造优先队列时使用。
堆可以被看成一棵树,节点在堆中的高度定义为从本节点到叶子的最长简单下降路径上边的数目;定义堆的高度为树根的高度。因为具有 n 个元素的堆是基于一棵完全二叉树,因而其高度为 Θ(lg n) 。
@@ -1255,94 +858,48 @@ RANDOMIZED-QUICKSORT 的平均运行情况是 O(n lg n),如果在递归的每
* 最差空间复杂度 O(n),辅助空间 O(1)
### 示例代码
-```
- 1 class Program
- 2 {
- 3 static void Main(string[] args)
- 4 {
- 5 int[] unsorted = { 4, 1, 5, 2, 6, 3, 7, 9, 8 };
- 6
- 7 HeapSort(unsorted);
- 8
- 9 foreach (var key in unsorted)
-10 {
-11 Console.Write("{0} ", key);
-12 }
-13
-14 Console.Read();
-15 }
-16
-17 static void HeapSort(int[] unsorted)
-18 {
-19 // build the heap in array so that largest value is at the root
-20 BuildMaxHeap(unsorted);
-21
-22 // swap root node and the last heap node
-23 for (int i = unsorted.Length - 1; i >= 1; i--)
-24 {
-25 // array[0] is the root and largest value.
-26 // the swap moves it in front of the sorted elements
-27 int max = unsorted[0];
-28 unsorted[0] = unsorted[i];
-29 unsorted[i] = max; // now, the largest one is at the end
-30
-31 // the swap ruined the heap property, so restore it
-32 // the heap size is reduced by one
-33 MaxHeapify(unsorted, 0, i - 1);
-34 }
-35 }
-36
-37 static void BuildMaxHeap(int[] unsorted)
-38 {
-39 // put elements of array in heap order, in-place
-40 // start is assigned the index in array of the last parent node
-41 // the last element in 0-based array is at index count-1;
-42 // find the parent of that element
-43 for (int i = (unsorted.Length / 2) - 1; i >= 0; i--)
-44 {
-45 // sift down the node at index start to the proper place
-46 // such that all nodes below the start index are in heap order
-47 MaxHeapify(unsorted, i, unsorted.Length - 1);
-48 }
-49 // after sifting down the root all nodes/elements are in heap order
-50 }
-51
-52 static void MaxHeapify(int[] unsorted, int root, int bottom)
-53 {
-54 int rootValue = unsorted[root];
-55 int maxChild = root * 2 + 1; // start from left child
-56
-57 // while the root has at least one child
-58 while (maxChild <= bottom)
-59 {
-60 // more children
-61 if (maxChild < bottom)
-62 {
-63 // if there is a right child and that child is greater
-64 if (unsorted[maxChild] < unsorted[maxChild + 1])
-65 {
-66 maxChild = maxChild + 1;
-67 }
-68 }
-69
-70 // compare roots and the older children
-71 if (rootValue < unsorted[maxChild])
-72 {
-73 unsorted[root] = unsorted[maxChild];
-74 root = maxChild;
-75
-76 // repeat to continue sifting down the child now
-77 maxChild = root * 2 + 1; // continue from left child
-78 }
-79 else
-80 {
-81 maxChild = bottom + 1;
-82 }
-83 }
-84
-85 unsorted[root] = rootValue;
-86 }
-87 }
+```C++
+// 堆排序
+// 向下调整
+void shift_down(vector &vec,int pos,int end){
+ // 不是最后的非叶节点,直接返回
+ if(pos>(end-1)/2)return;
+ int left = 2*pos+1;
+ int right = 2*pos+2;
+ int max;
+ // 超出范围,说明是最后一个非叶节点只有一个叶节点
+ // 找到两个节点中最大的那个
+ if(right>end || vec[left]>vec[right]){
+ max=left;
+ }
+ else{
+ max=right;
+ }
+ // 进行一次下降操作
+ if(vec[max]>vec[pos]){
+ swap(vec[max],vec[pos]);
+ }
+ // 下一层的下降
+ shift_down(vec,max,end);
+}
+
+void heap_sort(vector &vec){
+ int end = vec.size()-1;
+ // 从最后一个非页节点开始向下调整。到最后一个节点
+ for(int i=(end-1)/2;i>=0;i--){
+ shift_down(vec,i,end);
+ }
+ swap(vec[0],vec[end]);
+ end--;
+ while(end>0){
+ // 从根节点开始向下调整到最后一个叶节点。
+ shift_down(vec,0,end);
+ // 交换根节点和最后一个叶子节点
+ swap(vec[0],vec[end]);
+ end--;
+ }
+ return;
+}
```
## 9 内省排序(Introspective Sort)
diff --git a/算法/A类:基本算法/3.4.cpp b/算法/A类:基本算法/3.4.cpp
index e69de29b..66dc16b2 100644
--- a/算法/A类:基本算法/3.4.cpp
+++ b/算法/A类:基本算法/3.4.cpp
@@ -0,0 +1,175 @@
+#include
+#include
+
+using namespace std;
+
+// 插入排序
+void insertion_sort(vector &vec);
+// 冒泡排序
+void bubble_sort(vector &vec);
+// 选择排序
+void selection_sort(vector &vec);
+// 快速排序
+void quick_sort(vector &vec,int left,int right);
+// 归并排序
+void merge_sort(vector &vec,int left,int right);
+// 堆排序
+void heap_sort(vector &vec);
+int main(){
+ vector vec{6,3,1,4,9,7,8,2,5,0};
+ // bubble_sort(vec);
+ // selection_sort(vec);
+ // insertion_sort(vec);
+ // quick_sort(vec,0,vec.size()-1);
+ // merge_sort(vec,0,vec.size()-1);
+ heap_sort(vec);
+ for(int i=0;i &vec){
+ for(int i=1;i0;j--){
+ if(vec[j-1]>temp){
+ vec[j]=vec[j-1];
+ }
+ else{
+ break;
+ }
+ }
+ vec[j]=temp;
+ }
+ return ;
+}
+// 冒泡排序
+void bubble_sort(vector &vec){
+ for(int i=0;ivec[j+1]){
+ swap(vec[j],vec[j+1]);
+ }
+ }
+ }
+ return ;
+}
+// 选择排序
+void selection_sort(vector &vec){
+ int min=INT_MAX,min_index=0;
+ int i=0,j=0;
+ for(i=0;i&vec, int left, int right){
+ int index = right;
+ // 哨兵
+ int sentinel = vec[index];
+ // 子数组长度为 right - left + 1
+ int i = left;
+ // 从左到右,小的与前边交换。大的就会到右边。
+ for (int j = left; j <= right - 1; j++){
+ if (vec[j] <= sentinel){
+ swap(vec[i],vec[j]);
+ i++;
+ }
+ }
+ swap(vec[i],vec[index]);
+ return i;
+}
+// 尾递归。先头递归
+void quick_sort(vector &vec,int left,int right){
+ if(left>=right)return ;
+ int index = partion(vec,left,right);
+ quick_sort(vec,left,index-1);
+ quick_sort(vec,index+1,right);
+ return ;
+}
+// 归并排序
+void merge(vector &vec,int left,int right,int mid){
+ vector temp(vec);
+ int left_index=left;
+ int right_index = mid+1;
+ int i=left;
+ while(left_index<=mid && right_index<=right){
+ if(temp[left_index]<=temp[right_index]){
+ vec[i++]=temp[left_index++];
+ }
+ else{
+ vec[i++]=temp[right_index++];
+ }
+ }
+ // 处理左边没有用完的数据。(右边没有用完的可以保留在原地
+ while(left_index<=mid){
+ vec[i++]=temp[left_index++];
+ }
+ return;
+}
+// 头递归
+void merge_sort(vector &vec,int left,int right){
+ if(left>=right)return;
+ // divide
+ int mid = (left+right)/2;
+ // conquer
+ merge_sort(vec,left,mid);
+ merge_sort(vec,mid+1,right);
+ // combine
+ merge(vec,left,right,mid);
+ return;
+}
+
+// 堆排序
+// 向下调整
+void shift_down(vector &vec,int pos,int end){
+ // 不是最后的非叶节点,直接返回
+ if(pos>(end-1)/2)return;
+ int left = 2*pos+1;
+ int right = 2*pos+2;
+ int max;
+ // 超出范围,说明是最后一个非叶节点只有一个叶节点
+ // 找到两个节点中最大的那个
+ if(right>end || vec[left]>vec[right]){
+ max=left;
+ }
+ else{
+ max=right;
+ }
+ // 进行一次下降操作
+ if(vec[max]>vec[pos]){
+ swap(vec[max],vec[pos]);
+ }
+ // 下一层的下降
+ shift_down(vec,max,end);
+}
+
+void heap_sort(vector &vec){
+ int end = vec.size()-1;
+ // 从最后一个非页节点开始向下调整。到最后一个节点
+ for(int i=(end-1)/2;i>=0;i--){
+ shift_down(vec,i,end);
+ }
+ swap(vec[0],vec[end]);
+ end--;
+ while(end>0){
+ // 从根节点开始向下调整到最后一个叶节点。
+ shift_down(vec,0,end);
+ // 交换根节点和最后一个叶子节点
+ swap(vec[0],vec[end]);
+ end--;
+ }
+ return;
+}
diff --git a/算法/A类:基本算法/4.5 约瑟夫问题.md b/算法/A类:基本算法/4.5 约瑟夫问题.md
index e69de29b..d64a3866 100644
--- a/算法/A类:基本算法/4.5 约瑟夫问题.md
+++ b/算法/A类:基本算法/4.5 约瑟夫问题.md
@@ -0,0 +1,56 @@
+# 约瑟夫问题
+
+
+### 问题描述
+
+
+### 问题分析
+
+
+### 算法设计
+
+我们将上述问题建模为函数 f(n, m),该函数的返回值为最终留下的元素的序号。
+
+首先,长度为 n 的序列会先删除第 m % n 个元素,然后剩下一个长度为 n - 1 的序列。那么,我们可以递归地求解 f(n - 1, m),就可以知道对于剩下的 n - 1 个元素,最终会留下第几个元素,我们设答案为 x = f(n - 1, m)。
+
+由于我们删除了第 m % n 个元素,将序列的长度变为 n - 1。当我们知道了 f(n - 1, m) 对应的答案 x 之后,我们也就可以知道,长度为 n 的序列最后一个删除的元素,应当是从 m % n 开始数的第 x 个元素。因此有 f(n, m) = (m % n + x) % n = (m + x) % n。
+
+
+
+### 算法分析
+
+
+### 算法实现
+
+* 递归
+
+```
+class Solution {
+ int f(int n, int m) {
+ if (n == 1) {
+ return 0;
+ }
+ int x = f(n - 1, m);
+ return (m + x) % n;
+ }
+public:
+ int lastRemaining(int n, int m) {
+ return f(n, m);
+ }
+};
+```
+* 迭代
+
+```
+class Solution {
+public:
+ int lastRemaining(int n, int m) {
+ int f = 0;
+ for (int i = 2; i != n + 1; ++i) {
+ f = (m + f) % i;
+ }
+ return f;
+ }
+};
+```
+
diff --git a/算法/A类:基本算法/5 动态规划.md b/算法/A类:基本算法/5 动态规划.md
index 6c0102da..c0e069b7 100644
--- a/算法/A类:基本算法/5 动态规划.md
+++ b/算法/A类:基本算法/5 动态规划.md
@@ -47,13 +47,13 @@ $$
4. 根据计算最优值时的到的信息,**构造最有解**。
### 动态规划算法的步骤
-1. 正确选择**状态变量**xk, 使它既能描述过程的状态,又要满足无后效性。动态规划中的状态与一般所说的状态概念是不同的,它必须具有三个特性:
+1. **选择状态变量$x_k$**:描述过程的状态,又要满足无后效性。动态规划中的状态与一般所说的状态概念是不同的,它必须具有三个特性:
* 要能够用来描述受控过程的演变特征。
* 要满足无后效性。 所谓无后效性是指:如果某段状态给定,则在这段以后过程的发展不受前面各阶段状态的影响。
* 可知性。即是规定的各段状态变量的值,由直接或间接都是可以知道的。
-2. 确定**决策变量**uk及每段的允许决策集合Dk(xk)={uk}
-3. 写出**状态转移方程**如果给定第k段状态变量xk的值,则该段的决策变量uk一经确定,第k+1段状态变量xk+1的值也就完全确定。
-4. 列出**指标函数**Vk,n 关系,并要满足递推性。
+2. **确定决策变量$u_k$** :及每段的允许决策集合$D_k(x_k)=\{u_k\}$
+3. **确定状态转移方程** :如果给定第k段状态变量$x_k$的值,则该段的决策变量uk一经确定,第k+1段状态变量$x_{k+1}$的值也就完全确定。
+4. **确定指标函数$v_k$**:写出$v_k$和$n$关系,并要满足递推性。
### 动态规划最关键的部分
* 确定规模的增长方向。一般在动态规划问题中。规模可变的并不只有一个。比如在正则表达式与字符串的匹配问题中。字符串的规模可以变化,正则表达式的规模也可以变化。
diff --git a/算法/A类:基本算法/5.12 n个骰子的点数.md b/算法/A类:基本算法/5.12 n个骰子的点数.md
index e69de29b..29f75829 100644
--- a/算法/A类:基本算法/5.12 n个骰子的点数.md
+++ b/算法/A类:基本算法/5.12 n个骰子的点数.md
@@ -0,0 +1,104 @@
+# n个骰子的点数
+
+
+
+## 1 n个骰子的点数
+
+### 问题描述
+
+* 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
+
+* 示例 1:
+```
+输入: 1
+输出: [0.16667,0.16667,0.16667,0.16667,0.16667,0.16667]
+示例 2:
+
+输入: 2
+输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]
+```
+
+### 问题分析
+
+
+### 策略选择
+
+
+### 算法设计
+
+* 使用动态规划解决问题一般分为三步:
+ 1. 确定状态变量
+ 2. 确定状态转移方程
+ 3. 边界处理
+
+* 下面我们一步一步分析,相信你一定会有所收获!
+
+* 表示状态
+ * 分析问题的状态时,不要分析整体,只分析最后一个阶段即可!因为动态规划问题都是划分为多个阶段的,各个阶段的状态表示都是一样,而我们的最终答案在就是在最后一个阶段。
+ * 通过题目我们知道一共投掷 n 枚骰子,那最后一个阶段很显然就是:当投掷完 n 枚骰子后,各个点数出现的次数。
+* 注意,这里的点数指的是前 n 枚骰子的点数和,而不是第 n 枚骰子的点数,下文同理。找出了最后一个阶段,那状态表示就简单了。
+ * 首先用数组的第一维来表示阶段,也就是投掷完了几枚骰子。
+ * 然后用第二维来表示投掷完这些骰子后,可能出现的点数。
+ * 数组的值就表示,该阶段各个点数出现的次数。
+ * 所以状态表示就是这样的:dp[i][j]dp[i][j] ,表示投掷完 ii 枚骰子后,点数 jj 的出现次数。
+* 找出状态转移方程
+ * 找状态转移方程也就是找各个阶段之间的转化关系,同样我们还是只需分析最后一个阶段,分析它的状态是如何得到的。
+ * 最后一个阶段也就是投掷完 nn 枚骰子后的这个阶段,我们用 dp[n][j]来表示最后一个阶段点数 j出现的次数。
+ * 单单看第 n 枚骰子,它的点数可能为 1 , 2, 3, ... , 6因此投掷完 n 枚骰子后点数 j 出现的次数,可以由投掷完n−1 枚骰子后,对应点数 j-1, j-2, j-3, ... , j-6出现的次数之和转化过来。
+
+```
+for (第n枚骰子的点数 i = 1; i <= 6; i ++) {
+ dp[n][j] += dp[n-1][j - i]
+}
+```
+ * 写成数学公式是这样的:
+$$
+dp[n][j] = \sum_{i=1}^6 dp[n-1][j-i]
+$$
+ * n 表示阶段,jj 表示投掷完 nn 枚骰子后的点数和,ii 表示第 nn 枚骰子会出现的六个点数。
+
+* 边界处理
+ * 这里的边界处理很简单,只要我们把可以直接知道的状态初始化就好了。
+ * 我们可以直接知道的状态是啥,就是第一阶段的状态:投掷完 11 枚骰子后,它的可能点数分别为 1, 2, 3, ... , 61,2,3,...,6 ,并且每个点数出现的次数都是 11 .
+
+```
+for (int i = 1; i <= 6; i ++) {
+ dp[1][i] = 1;
+}
+```
+
+
+
+### 算法分析
+* 时间复杂度 $O(n ^ 2)$
+* 空间复杂度 $O(n)$
+### 算法实现
+
+```C++
+class Solution {
+public:
+ vector twoSum(int n) {
+ int dp[15][70];
+ memset(dp, 0, sizeof(dp));
+ for (int i = 1; i <= 6; i ++) {
+ dp[1][i] = 1;
+ }
+ for (int i = 2; i <= n; i ++) {
+ for (int j = i; j <= 6*i; j ++) {
+ for (int cur = 1; cur <= 6; cur ++) {
+ if (j - cur <= 0) {
+ break;
+ }
+ dp[i][j] += dp[i-1][j-cur];
+ }
+ }
+ }
+ int all = pow(6, n);
+ vector ret;
+ for (int i = n; i <= 6 * n; i ++) {
+ ret.push_back(dp[n][i] * 1.0 / all);
+ }
+ return ret;
+ }
+};
+```
\ No newline at end of file
diff --git a/算法/A类:基本算法/5.13 正则表达式的匹配.md b/算法/A类:基本算法/5.13 正则表达式的匹配.md
index b648a31c..4b30e463 100644
--- a/算法/A类:基本算法/5.13 正则表达式的匹配.md
+++ b/算法/A类:基本算法/5.13 正则表达式的匹配.md
@@ -21,7 +21,7 @@
### 算法设计
-* 设s的长度为n ,pp 的长度为 m ;将 s 的第 i 个字符记为 s_i,p 的第 j个字符记为 p_j ,将 s 的前 i 个字符组成的子字符串记为s[:i] , 同理将 p 的前 j 个字符组成的子字符串记为 p[:j]p[:j] 。
+* 设s的长度为n ,p 的长度为 m ;将 s 的第 i 个字符记为$s_i$,p 的第 j个字符记为 $p_j$ ,将 s 的前 i 个字符组成的子字符串记为s[:i] , 同理将 p 的前 j 个字符组成的子字符串记为 p[:j]p[:j] 。
* 因此,本题可转化为求s[:n] 是否能和p[:m] 匹配。
@@ -29,7 +29,7 @@
1. 添加一个字符 $s_{i+1}$后是否能匹配?
2. 添加字符 $p_{j+1}$后是否能匹配?
-* 本题的状态共有 m \times nm×n 种,应定义状态矩阵 dpdp ,dp[i][j]代表 s[:i]与 p[:j]是否可以匹配。做好状态定义,接下来就是根据 「普通字符」 , 「.」 , 「*」三种字符的功能定义,分析出动态规划的转移方程。
+* 本题的状态共有 m \times nm×n 种,应定义状态矩阵dp ,dp[i][j]代表 s[:i]与 p[:j]是否可以匹配。做好状态定义,接下来就是根据 「普通字符」 , 「.」 , 「*」三种字符的功能定义,分析出动态规划的转移方程。
1. **状态定义**: 设动态规划矩阵 dp , dp[i][j] 代表字符串 s 的前 i 个字符和 p 的前 j 个字符能否匹配。
2. **转移方程**: 需要注意,由于 dp[0][0] 代表的是空字符的状态, 因此 dp[i][j] 对应的添加字符是 s[i - 1] 和 p[j - 1] 。
diff --git a/算法/A类:基本算法/5.6 最大子段和问题.md b/算法/A类:基本算法/5.6 最大子段和问题.md
index f0344a22..3f9662d8 100644
--- a/算法/A类:基本算法/5.6 最大子段和问题.md
+++ b/算法/A类:基本算法/5.6 最大子段和问题.md
@@ -14,7 +14,7 @@
* 初始状态: dp[0] = nums[0]dp[0]=nums[0],即以 nums[0]nums[0] 结尾的连续子数组最大和为 nums[0]nums[0] 。
* 返回值: 返回 dpdp 列表中的最大值,代表全局最大值。
-
+
### 算法分析
diff --git a/算法/A类:基本算法/image/2021-03-19-00-24-38.png b/算法/A类:基本算法/image/2021-03-19-00-24-38.png
deleted file mode 100644
index 915a38e4..00000000
Binary files a/算法/A类:基本算法/image/2021-03-19-00-24-38.png and /dev/null differ
diff --git a/算法/A类:基本算法/image/2021-03-29-09-47-50.png b/算法/A类:基本算法/image/2021-03-29-09-47-50.png
new file mode 100644
index 00000000..3c7780d8
Binary files /dev/null and b/算法/A类:基本算法/image/2021-03-29-09-47-50.png differ
diff --git a/算法/A类:基本算法/image/2021-03-29-09-50-50.png b/算法/A类:基本算法/image/2021-03-29-09-50-50.png
new file mode 100644
index 00000000..5dbc74e9
Binary files /dev/null and b/算法/A类:基本算法/image/2021-03-29-09-50-50.png differ
diff --git a/算法/A类:基本算法/image/2021-03-29-10-18-28.png b/算法/A类:基本算法/image/2021-03-29-10-18-28.png
new file mode 100644
index 00000000..b1f42319
Binary files /dev/null and b/算法/A类:基本算法/image/2021-03-29-10-18-28.png differ
diff --git a/算法/A类:基本算法/image/蛮力法-顺序查找.png b/算法/A类:基本算法/image/蛮力法-顺序查找.png
deleted file mode 100644
index 40b3ce77..00000000
Binary files a/算法/A类:基本算法/image/蛮力法-顺序查找.png and /dev/null differ
diff --git a/算法/C类:问题类型算法/1.3 最近对问题.md b/算法/C类:问题类型算法/1.3 最近对问题.md
new file mode 100644
index 00000000..5b744e28
--- /dev/null
+++ b/算法/C类:问题类型算法/1.3 最近对问题.md
@@ -0,0 +1,24 @@
+
+## 最近对问题
+### 理解问题
+* 找出一个包含n个点的集合中距离最近的两个点。
+### 选择策略
+* 分别计算每一点对之间的距离,然后从中找出距离最小的那一对。为了避免同一点对计算两次,可以只考虑i