第二章 进程和线程
2.1 进程(Process)
进程模型
- 单CPU伪并行,区分于多处理器系统
一个进程就是一个正在执行程序的实例,有程序、输入、输出以及状态
进程的创建
- 启动操作系统时:守护进程概念
- 系统调用,进程创建新辅助进程
- 用户创建
- 批处理作业的初始化
- 每个进程有自己的地址空间
- 进程创建之后,父进程和子进程有各自不同的地址空间
进程的终止
进程的层次结构
进程的状态
- 一个进程在逻辑上不能运行时,会被阻塞,典型的例子就是等待可以使用的输入,进入阻塞态
- 三个状态:1运行态、2就绪态(暂时没有cpu分配)、3阻塞态
- 调度程序:1和2之间的转换
- 外部事件发生时:3->2->1
2.2 线程(Thread)
并行线程在同一个地址空间运行。线程可在用户态实现,也可在内核态实现。
- 传统操作系统中,每个进程有一个地址空间和一个控制线程,也经常存在同一地址空间并行运行多个控制线程的情形。
- 线程比进程更轻量级,更容易创建和撤销
多线程并行 vs 单线程中断操作
多线程可以共享公共内存,使用多个进程做不到
- 阻塞系统调用(线程、进程)
线程模型
线程必须在某个进程中执行,进程用于把资源集中在一起,线程则是在CPU上被执行调度的实体
- 在同一个进程中并行运行多个线程,是对同一台计算机上并行运行多个进程的模拟。
多线程共享同一个地址空间和其他资源,多个进程共享物理内存、磁盘和其他资源
- 每个线程有自己的堆栈,存放相应过程的局部变量和过程调用完成之后的返回地址
- 线程带来的复杂性:父子进程和多线程之间的关系
在用户空间和内核实现线程的区别
2.3 进程间通信IPC
进程间通过IPC交换信息,如信号量、管程和消息,确保不会有两个进程同时处在临界区。
- 共享内存、消息传递
1. 三个问题:
- 进程间怎么传递信息
- 确保两个或多个进程在关键活动中不会交叉 (同样适用于线程)
- 进程间的顺序 (同样适用于线程)
协作的进程可能共享彼此都能读写的存储区,可能在内存中也可能是个共享文件
2. 竞争条件:多个进程同时读写共享区数据,导致结果由精确的时序决定
- 需要阻止多个进程同时读写共享区的数据 -> 互斥
3. 临界区:对共享内存进行访问的程序片段
任何两个进程不能同时处于临界区
4. 忙等待的互斥
- 几种实现互斥的方案:
- 屏蔽中断:一个进程进入临界区后屏蔽其他进程
- 临界区锁变量
- 轮换
一个进程进入临界区前进行检查,不允许则进程原地等待(忙等待),直到允许为止
5. 睡眠与唤醒
-
生产者消费者问题:
消费者读取数据区count值为0 ---> 调度程序暂停消费者,启动生产者 ---> 生产者往缓冲区加入一个数据项,count=1 ---> 唤醒消费者,但是消费者可能还未睡眠(调度程序) ---> count=0,消费者睡眠,缓冲区满后生产者睡眠 ---> 两个进程睡眠
6. 信号量、互斥量和管程
7. 消息传递
send(destination, &message);
receive(source, &message);
-
消息传递 vs 内存共享
- 由操作系统自动缓存,使用n条信息,类似于共享内存区的n个slot
- 生产者取走一个空消息,送回一条填充了内容的消息,消费者再取走。
-
信箱:对信息进行缓存的数据结构,send和receive的地址参数就是信箱地址,而不是进程地址。
8. 屏障
- 用于进程组,而不是双进程的消费者-生产者情景
2.4 调度
1. 何时调度
- 创建新进程后,先父还是先子。
- 一个进程退出时,进程集中选择
- 中断发生时
2. 调度算法分类
三种环境:
- 批处理(非抢占式算法)
- 交互式
- 实时
3. 批处理服务的调度
- 非抢占式的先到先服务,单链表队列
- 最短作业优先
- 最短剩余时间优先
4. 交互式系统的调度
- 时间片轮转调度 (默认进程同等重要)
- 优先级调度
- 最短进程优先
- 保证调度、彩票调度(不平等保护)
5. 实时系统的调度
6. 线程调度
2.5 经典的IPC问题
-
就餐问题(有限资源的竞争问题): 死锁(进程同时启动占满cpu导致一个也运行不了) 或者 饥饿(同时启动又同时终止)
--->需解决问题并获得最大并行度 - 读-写问题: 读写不能同时进行,典型为数据库。如果正在读,则写进程被挂起,如果存在read流,则写进程可能永远没有机会。
第三章 内存管理
3.1 无存储器抽象
- 直接把物理地址暴露给进程,带来的问题:一是程序容易故意或者偶然的破坏系统,二是难以同时运行多个程序。
3.2 一种存储器抽象:地址空间
- 使多个程序同时处于内存中并且不相互影响,需保护和重定位
- 地址空间 与 物理内存 之间存在映射,可以理解为抽象的物理内存
地址空间是一个进程用于内存寻址的一套地址集合,每个进程都有自己的地址空间,且每个进程的地址空间都是独立的(除特殊情况进程需共享)
每个进程的地址空间是独立的,比如一个进程地址28与另一个进程28是不一样的,可理解为相对地址而不是绝对地址。
-
基址寄存器和界限寄存器: 分别存储程序起始地址 和 程序长度
- 优点:这样就给每个进程提供了简单的私有地址空间
- 缺点:每次访问内存都要进行加法和比较运算
3.3 两种处理内存超载的技术:交换技术 和 虚拟内存
- 交换技术(物理内存上):** 把一个进程完整调入内存,运行一段时间,然后存回磁盘。空闲进程主要存储在磁盘上。
- 虚拟内存(使用地址空间):** 每个程序有自己的地址空间,这个空间被分成多个块,每一块称为页面(分页技术)。每一页有连续的地址范围。这些页被映射到物理内存,但并不是所有的页都必须在内存中才能运行程序。程序引用到一部分物理内存中的地址空间时,硬件立刻执行映射。引用到不在物理内存的地址空间(虚拟地址空间)** 时,系统将缺失的部分装入物理内存并重新执行对应的指令。
- 分页与页表:
分页有关的操作发生在四个时间段:进程创建时、进程执行时、缺页中断时、进程终止时。
地址空间的页面对应于物理空间的页框
3.4 页面置换算法(虚拟内存)
- 当程序访问不在内存中的页面时,引起缺页中断,进行页面的置换。
- 最优页面置换算法: 发生缺页中断时,先置换标记最大的页面。标记是指该页面在多少条指令之后才会被访问。不可实现,用作比较基准。
- 最近未使用页面置换算法(NRU): LRU粗糙的近似。
- FIFO算法(置换存在时间久的,可能抛弃重要页面) 和 第二次机会算法(存在时间久且没被使用)
- 最近最少使用页面置换算法(LRU): 置换未使用时间最长的页面,只能通过特定的硬件实现,可用软件模拟。
- 最好的两种算法:老化算法 和 工作集时钟算法,分别基于LRU和工作集。
3.5 分页系统的设计问题
问题:发生缺页中断并进行页面置换时,置换同一个进程的页面还是所有进程中的页面?
局部分配策略 和 全局分配策略
负载控制
- 减少内存竞争的一个好方法是 将一部分进程交换到磁盘,即使使用虚拟内存技术分页,也需要交换技术,进行二级调度。
地址空间中分离 指令空间 和 数据空间
共享页面
- 多用户同时运行同一个程序,使用共享页面避免了内存中有一个页面的两个副本,效率更高。多进程可以使用同一个指令空间和不同的数据空间。
共享库(特例) 和 内存映射文件(通用)
3.6 分段
使程序指令和数据可以被划分为逻辑上相互独立的地址空间且有助于共享和保护 ---> 指令空间和数据空间
第四章 文件系统
长期存储信息
-
三个基本要求:
- 能够存储大量信息
- 使用信息的进程终止时,信息仍然存在
- 能使多个进程并发访问
-
路径名:Windows“\”, Unix“/”
./ 当前目录
../ 往上目录
文件的实现
- 连续分配
- 链表分配:文件分配表FAT
目录的实现(树)
查找:顺序查找、散列表查找
虚拟文件系统VFS
小结
- 从外部看,文件系统是一组文件和目录,以及对文件和目录的操作。
第六章 死锁
死锁的定义: 一个进程集合中的每个进程都在等待只能由该进程集合中其他进程进行才能引发的事件,则该进程集合就是死锁的。
资源间的竞争造成死锁
可抢占资源 与 不可抢占资源
资源死锁
死锁进程集合中的每个进程都在等待其他死锁进程所占有的资源
-
资源死锁的条件:
- 资源要么已经分配给了一个进程,要么是可用的。(互斥条件)
- 已得到某个资源的进程可以再请求新的资源。(占有和等待条件)
- 分配给一个进程的资源不能被强制性抢占,只能通过占有它的进程显示释放。(不可抢占条件)
- 死锁发生时,一定有两个或者两个以上的进程组成的环路。(环路等待条件)
每个死锁的条件都能找到对应的可选解决死锁策略。
死锁的建模:资源进程 有向图/矩阵
四种处理死锁的办法
- 鸵鸟算法: 忽略问题
- 死锁检测和恢复:
- 检测:检测有向图是否存在一个或以上的环路
- 恢复:抢占恢复、回滚恢复、杀死进程
- 死锁避免: 基于安全状态的资源轨迹图、银行家算法
从本质上来说是不可能的,因为需要获取未知的请求
- 死锁预防: 至少破坏四个条件之一即可。
其他问题
- 通信死锁:解决方案 ---> 超时
- 活锁: 当进程意识到获取不到下一个需要的资源时选择释放,等待后再尝试 ---> 导致饥饿问题
第七章 虚拟化和云
把各个服务器放在独立的计算机之上,实现隔离和容错。(沙盒)
云的功能是提供一个用户可以直接访问并任意使用的虚拟机,将计算资源集中到少数地方实现规模效益。IaaS / PaaS / SaaS
第八章 多处理机系统
- 共享存储器多处理机
- 多计算机
- 分布式系统
网友评论