Contents

操作系统复习笔记

一 绪论

OS的作用

  • 用户与硬件之间的接口
  • 管理计算机资源
  • 抽象计算机资源

OS的发展

  • 单道批处理系统
    • 用户程序交给监控程序,由监控程序控制作业一个接一个交给IO处理
    • CPU等待IO、内存浪费、资源浪费
  • 多道批处理系统
    • 当一个作业在等待IO时,处理器可以切换到另一个不在等待IO的作业
    • 中断:中断机构(硬件)发出信号,CPU转而处理中断程序工作,完成后再返回原来的工作
    • 通道:专门负责输入输出的硬件,支持CPU和IO并行执行
    • 作业的四种状态:
      • 提交、后备、运行、完成
    • 三级调度
      • 低级调度:内存与内存
      • 中级调度:内存与交换区
      • 高级调度:外存到内存
    • 多道程序设计好处
      • CPU利用率
      • 内存和IO设备利用率
      • 系统吞吐量
    • 缺点
      • 周转时间长
      • 无交互能力
  • 分时系统、实时系统、微机操作系统
  • 操作系统的特征
    • 并发、共享、异步、虚拟
      • 概念区分:并发与并行、同步与异步

二 OS结构

陷阱和中断

  • 中断:外部的被迫中断
  • 陷阱:程序的主动中断

双模式

计算机硬件通过模式位表示当前为内核模式或用户模式,区分操作系统执行的任务和用户执行的任务。可能引起损害的机器指令为特权指令,只有内核模式才可以执行特权指令。模式概念可以扩展为超过两个模式。

系统调用

当要执行系统调用时,硬件通常将它作为软件中断。控制通过中断向量转到操作系统的中断服务程序,并且模式位也设为内核模式。内核首先验证参数是否正确和合法,执行请求,最后控制返回到系统调用之后的指令。

定时器

为了防止用户程序陷入死循环,或者不调用系统服务且不将控制返回给操作系统,可以使用定时器,设置指定周期后中断计算机。

三 进程与线程

进程的定义

一个具有一定独立功能的可并发执行的程序,在一个数据集合上的运行过程

进程与程序

运行的动态实体与静态实体

进程的状态

  • 新建状态、就绪状态、运行状态、阻塞状态、终止状态

挂起

  • 挂起/解挂的原因:用户、进程、系统的需要
  • 增加挂起状态后:活动就绪、静止就绪、活动阻塞、静止阻塞

PCB

PCB是用以记录与进程相关信息的主存区,是进程存在的唯一标志

  • PCB的组织方式
    • 线性方式、链接方式、索引方式
  • 进程切换
    • P0->系统中断->[保存PCB0->…->加载PCB1]->P1->系统中断->[保存PCB1->…->加载PCB0]->P0

进程创建与终止

  • 进程图:用于描述进程家族关系的有向树,箭头表示创建关系
  • 进程创建:
    • 申请空白PCB
    • 为新进程分配资源
    • 初始化PCB
    • 将新进程插入就绪队列
  • 进程终止:
    • 根据终止进程标识符,找到对应PCB
    • 若该进程正在执行,终止进程,设置调度标志为真
    • 如果该进程具有子孙进程,则终止其所有子孙
    • 回收所有资源,归还给其父进程或系统
    • 将PCB移出原所在队列

进程通信

协作进程需要一种进程间通信机制(Interprocess Communicatio,IPC)来允许进程相互交互数据与信息

  • 进程通信类型
    • 共享存储器系统
    • 消息传递系统
      • 直接通信:Send(Receiver, msg), Receive(Sender, msg)
      • 间接通信(信箱):Send(mailbox, msg), Receive(mailbox, msg)
      • 消息缓冲队列通信机制:生产者-消费者
    • 管道通信
      • 管道:用于连接一个读进程和一个写进程,以实现它们之间通信的共享文件,又称为Pipe文件

线程

是进程中的一个实体,是能被系统独立调度和分派的基本单位

  • 基本状态:就绪、执行、堵塞
  • 基本操作:派生、调度、阻塞、激活、结束

四 进程调度

  • 三级调度模型
    • 高级调度(作业调度):后备队列->内存(长程调度)
    • 低级调度(进程调度):就绪队列->运行(短程调度)
    • 中级调度(进程调度):内存<->交换区
  • 调度算法
    • 先来先服务(FCFS)
    • 短作业优先(SJF) - 抢占式/非抢占式
    • 优先级调度 - 抢占式/非抢占式
    • 时间片轮转(RR)
    • 多级队列
      • 不同队列调度算法可以不同
      • 队列之间有优先级差异或时间片分配
    • 多级反馈队列
      • 进程可在队列之间移动
      • 参数:
        • 队列数量
        • 每个队列的调度算法
        • 用以确定何时升级到更高优先级队列的方法
        • 用以确定何时降级到更低优先级队列的方法
        • 用以确定进程在需要服务时将会进入哪个队列的方法

五 进程同步

Peterson算法

两个进程互相谦让

1
2
3
4
5
6
7
8
while (true) {
  flag[i] = TRUE;
  turn = j;
  while ( flag[j] && turn == j);
  CRITICAL SECTION
  flag[i] = FALSE;
  REMAINDER SECTION
}

信号量机制

1
2
3
4
5
6
7
8
9
semaphore mutex=1;
process_1(){ 
  while(true) {
    wait(mutex);
    critical section;
    signal(mutex);
    remainder section;
  }
}

生产者-消费者

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Semaphore muter=1, empty=N, full=0;

Producer() {
  while (true) {
    produce item v;
    wait(empty);
    wait(mutex);
    b[in] = v;
    in = (in+1)%N;
    signal(mutex);
    signal(full);
  }
}

Comsumer() {
  while (true) {
    wait(full);
    wait(mutex);
    w = b[out];
    out = (out+1)%N;
    signal(mutex);
    signal(empty);
    consume item w;
  }
}

读者-写者问题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Semaphore mutex=1, db=1;
int readercount=0;

Reader() {
  while (true) {
    wait(mutex);
    readcount++;
    if (readcount == 1) {
      wait(db);
    }
    signal(mutex);
    Reading;
    wait(mutex);
    readcount--;
    if (readcount == 0) {
      signal(db);
    }
    signal(mutex);
  }
}

Writer() {
  while (true) {
    wait(db);
    writing;
    signal(db);
  }
}

管程

  • 条件变量:condition x, y;
    • 每个条件变量都关联了一个队列,包含因该条件而阻塞的进程,对条件变量仅有的操作是wait()、signal()
  • x.wait():
    • 将自己阻塞在等待队列中
    • 唤醒一个等待者或者释放管程的互斥访问
  • x.signal():
    • 将等待队列中的一个线程唤醒
    • 如果等待队列为空,则等同空操作

哲学家就餐问题(管程)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
monitor DP
{ 
  enum { THINKING, HUNGRY, EATING} state [5] ;
  condition self [5];

  void pickup (int i) { 
    state[i] = HUNGRY;
    test(i);
    if (state[i] != EATING) self [i].wait;
  }

  void putdown (int i) { 
    state[i] = THINKING;
    // testing left and right neighbors
    test((i + 4) % 5);
    test((i + 1) % 5);
  }

  void test (int i) { 
    if ( (state[(i + 4) % 5] != EATING) 
      && (state[i] == HUNGRY) 
      && (state[(i + 1) % 5] != EATING) ) { 
      state[i] = EATING ;
      self[i].signal () ;
    }
  }

  initialization_code() { 
    for (int i = 0; i < 5; i++)
      state[i] = THINKING;
  } 
}

六 死锁

多个进程因竞争资源而造成的一种僵局,若无外力作用,这些进程将永远无法推进

死锁发生的必要条件

  • 互斥
  • 非抢占
  • 占有并等待
  • 循环等待

资源分配图

  • 无环一定不死锁
  • 单资源有环一定死锁

死锁的处理方法

  • 死锁预防
    • 破坏占有并等待
      • 方法一:必须获得全部资源才能运行
      • 方法二:申请资源前必须释放自己已占有所有资源
    • 破坏非抢占
      • 方法一:进程申请某资源,有则分配,无则释放该进程所有资源并等待
      • 方法二:进程申请某资源,有则分配,否则检测有该资源的另一进程,若该进程在等待则抢占,否则申请资源的进程等待(允许被抢占资源)
    • 破坏循环等待
      • 给资源编号
      • 进程只能按递增顺序申请资源
      • 如果需要同一资源多个实例需一次申请
      • 申请编号更小资源时,需先将大编号资源全部释放
    • 破坏互斥
      • 临界资源不可能做到
  • 死锁避免
    • 系统的安全状态:Max, Allocation, Available
    • 若存在一分配顺序使进程全部执行的安全序列,则认为是安全状态
    • 银行家算法:Max, Allocation, Need, Available
  • 死锁检测
    • 单实例:分配图
    • 多实例:银行家
  • 死锁恢复
    • 进程终止
      • 终止全部死锁进程
      • 一次终止一个
    • 资源抢占
      • 选择一个牺牲品使代价最小
      • 回滚:将进程回滚到某安全状态
      • 饥饿:防止进程饥饿,需要有限牺牲某进程

七 存储管理

相关概念和术语

  • 逻辑地址(logical address)/相对地址:CPU所生成的地址,又称为虚拟地址(virtual address)
  • 物理地址(physical address)/绝对地址:内存单元所看到的地址(加载到内存地址寄存器中的地址)
  • 逻辑地址空间(logical address space):由程序所生成的所有逻辑地址的集合称为逻辑地址空间
  • 物理地址空间(physicaladdress space ):与逻辑地址对应的所有物理地址的集合称为物理地址空间
  • 重定位(relocation):从逻辑地址(虚拟地址)到物理地址的映射称为重定位,由内存管理单元(MMU)完成
  • 重定位寄存器:基址寄存器、限长寄存器
  • 绑定:从一个地址空间到另一个地址空间的映射

内存保护

  • 基地址寄存器:最小的合法的物理内存地址
  • 界限地址寄存器:指定范围的大小
  • 内存空间保护的实现通过CPU硬件对在用户模式下产生的地址与寄存器的地址进行比较来完成

用户程序处理过程

重定位

  • 静态重定位:程序装入主存之前由编译/链接程序完成重定位,入主存可立即执行
  • 动态重定位:程序入主存之前不进行重定位,入主后存执行到与地址相关项时,再进行重定位

装入方式

  • 绝对装入:程序在编译时完成静态重定位,按绝对地址装入内存
  • 可重定位装入:根据内存使用情况,将装入模块进行静态重定位后装入内存
  • 动态运行时装入:装入程序将装入模块装入内存后,不将装入模块的逻辑地址转换为物理地址,在执行时用重定位寄存器进行动态重定位

链接方式

  • 静态链接:程序运行之前,先将各目标模块以及所需库函数链接成一个完整的装入模块
  • 装入时动态链接:将用户源程序编译后所得到的一组目标模块,在装入内存时,采用边装入边链接的链接方式
    • 容易共享:每个库程序的引用都有一个存根,用于指出如何定位适当的内存驻留库程序
  • 运行时动态链接:将对某些目标模块的链接推迟到程序执行时才进行

连续分配存储管理

  • 单一连续分配
  • 固定分区分配
    • 内碎片
  • 动态分区分配/可变分区分配
    • 算法:
      • 首次适应
      • 循环首次适应
      • 最佳适应
      • 最差适应

碎片

  • 外碎片:内存中小块的空闲分区,无法单独满足任何一个进程的需求
  • 内碎片:固定分区分配方式中存在的,已经分配给进程,但进程不会使用的空闲空间
    • 紧缩、离散分配内存

覆盖与交换技术

  • 覆盖:进程内部区域的替换,主要用于早期操作系统
    • 把程序划分为若干功能上相对独立的程序段,按照自身逻辑结构将那些不会同时执行的程序段共享同一块内存区域
    • 程序段先保存在磁盘上,当有关程序段的前一部分执行结束,把后续程序段调入内存,覆盖前面的程序段
  • 交换:进程之间的替换
    • 当内存空间紧张时,系统将内存中某些进程暂时移到外存(盘交换区),把外存中某些进程换入内存中,替换移出进程原来的内存空间
    • 这种技术是进程在内存与外存之间的动态调度,多用于分时系统中
    • 中级调度:采用交换技术

分页存储管理

  • 分页(长度固定)
    • 分页思想
      • 内存物理地址空间按2n等分成页框/帧(frame),并从0连续编号:0,1,2,…
      • 作业的逻辑地址空间按页框/帧大小等分成页,并从0连续编号:0,1,2,…
      • 作业逻辑地址表示为:v=(p,d)
      • 作业连续的页,可以分配不连续的页框/帧
      • 系统设置页表PMT保存作业各页入内存后的情况,包含页号、页框号
      • 设置一个页表地址寄存器,保存当前执行进程页表的起始地址和页表的长度
  • 分段(长度可变)
  • 段页式(分段管理虚存,分页管理实存)

地址变换

直接地址变换

  • 借助页表、页表寄存器完成作业的逻辑地址(虚地址)到内存物理地址的变换
  • 页表基址寄存器(Page-table base register,PTBR)页表长度寄存器(Page-table length register,PRLR)

具有快表的地址变换

  • 增设若干具有并行查询能力的特殊高速缓冲寄存器(联想寄存器/快表),保存当前执行进程的部分页表
  • 程序的局部性特征

页表

页表是一种特殊的数据结构,放在系统空间的页表区,存放逻辑页与物理页帧的对应关系。 每一个进程都拥有一个自己的页表,PCB表中有指针指向页表

  • 层次页表
  • 哈希页表
  • 反置页表
    • 一般页表:每个进程都有一个相关的页表,这些页表可能消耗大量的物理内存
    • 反置页表:为每一个物理页框设置一个条目,并记录该物理页框所分配的进程ID和对应的逻辑页

八 虚存管理

请求分页机制

  • 在分页系统的基础上增加了请求调页功能和页面置换功能
  • 整个用户程序驻留在磁盘(二级存储)上,只装入少量页面入内存即可启动运行
  • 程序运行中,由调页程序(pager)根据需要将单个页面 从磁盘调入内存, 将不需要的页面换出到磁盘上
  • 置换时以页为单位
  • 硬件支持
    • 请求页表机制
    • 缺页中断机构
    • 地址变换机构

请求页表机制

  • 状态位P(有效-无效位):用于指示该页是否已经调入内存
  • 访问字段A:用于记录本页在一段时间内被访问的次数,或记录本页最近已有多长时间未被访问,以供置换算法在选择置换页面时参考
  • 修改位M(脏位):标识该页在调入内存后是否被修改过
  • 外存地址:该页在外存上的地址,一般指物理块号

缺页中断机构处理过程

  1. 访问进程页表,查看访问页是否合法
  2. 如果是非法访问,则终止进程访问;如果页面访 问合法,但该页不在内存中,则需要调入
  3. 在物理内存中找到一个空闲页框(free frame)
  4. 调度磁盘操作,将失效页从备用存储(磁盘)中 装入空闲页框
  5. 重置页表,修改页面信息
  6. 重启因缺页而中断的指令

地址变换机构(有快表)

  1. 存储保护检查:页号>页表长度?
    • 是,越界中断
    • 否则2
  2. 查快表
    • 找到,修改访问位对于写操作置修改位,形成物理地址访问
    • 若未找到,查页表状态位
      • 在主存,将表目写入快表
      • 否则,缺页中断

页面置换算法

基本页面置换流程

  • 查找所需页在磁盘上的位置
  • 查找一个空闲的页框:
    • 如果有空闲页框,那么就使用它
    • 如果有没有空闲页框,就使用页面置换算法以选 择一个“牺牲”页框(victim frame)
    • 将“牺牲”页框的内容写到磁盘上,修改页表和 页框表
  • 将所需页读入空闲页框,修改相应的页表和页 框表
  • 重启用户进程

页面置换算法详解

  • 评价指标:缺页率
  • 先进先出(FIFO)页面置换算法
  • 最佳(Optimal)置换算法(理论上)
    • 置换未来最长时间内不会访问的页面
  • 最近最少使用(LRU)页面置换算法
  • 近似LRU页面置换算法
    • 附加访问位算法
      • 为页表中的每一页保留一个8位的字节
      • 在规定的时间间隔(如每隔100ms)内,时钟定时器产生中断,OS将页面的访问位转移到8位字节的高位,其他位均向右移一位,最低位丢弃,这个8位字节记录了该页面在最近的8个时间间隔内的使用情况
      • 选择值最小的页面置换,相等情况下按照FIFO算法执行
    • 二次机会算法(Clock置换算法)
      • 页表中的每一页有一个访问位(页面被访问后将其置为1)
      • 按照FIFO的方式选择置换页,如果该页的访问位为1,则给予第二次机会,将其访问位置为0
  • 最不经常使用(Least Frequently Used,LFU)页面置换算法
  • 最常使用(Most Frequently Used,MFU)页面置换算法
    • 具有最小次数的页可能刚刚调入内存

页框分配算法

  • 固定分配算法
    • 平均分配
    • 按比例分配:进程大小
  • 基于优先级分配算法
    • 按照进程的优先级成比例给进程分配页框
    • 进程发生缺页中断时
      • 选择自己的页框进行页面置换
      • 选择优先级更低的进程的页框置换

全局分配与局部分配

  • 全局置换:允许从所有页框中置换
  • 局部置换:仅仅从分配给进程自己的页框中进行置换

请求分页系统的性能分析

抖动(thrashing)

  • CPU的利用率会随着道数的增加而提高,直到达到最大值
  • 达到最大值后继续提高道数,CPU的利用率将不再提高,反而急剧下降,这就是“系统抖动”
  • 为了提升CPU利用率,则需要减少道数,消除抖动

抖动产生的原因

  • 同时在系统中运行的进程太多,分配给每个进程的页框太少,不能满足进程正常运行的基本要求

工作集:进程在某段时间内实际访问页的集合

  • $WS(t,\Delta)$,$\Delta$为工作集尺寸
  • $D=sum(WS_n(…))$,$m$为页框数,若$D>m$,则挂起进程

预防抖动

  • 采取局部置换策略
  • 将工作集算法融入作业调度
  • 利用“L=S”准则调节缺页率
  • 选择暂停的进程

九 I/O系统

I/O系统的基本功能

  1. 隐藏物理设备的细节
  2. 与设备的无关性
  3. 提高处理机和I/O设备的利用率
  4. 对I/O设备进行控制
  5. 确保对设备的正确共享
  6. 错误处理

I/O系统的层次结构

  • 用户层软件
  • 设备独立性软件
  • 设备驱动程序
  • 中断驱动程序
  • 硬件

I/O系统接口

  • 块设备接口
  • 流设备接口
  • 网络通信接口

I/O系统结构

  • 总线型结构
  • 通道型结构

I/O控制方式

  • 程序直接控制方式
    • CPU轮询I/O设备
    • 程序直接控制I/O方式中CPU直接控制I/O操作的过程
    • CPU的绝大部分时间都处于等待I/O设备完成数据I/O的循环测试中
  • 中断驱动I/O控制方式
    • I/O控制器:一旦接受到CPU读命令,则开始读数据;完成读数据后发送中断信号表示已就绪,当CPU请求数据时传输数据,等待下一次I/O操作
    • CPU:CPU发出读信号以后继续其他工作,每个指令周期末尾检测中断信号,若检测到,则转向执行中断处理程序
  • DMA控制方式
    • 数据传输的基本单位是数据块
    • 所传送的数据是从设备直接送入内存的,或者相反
    • 仅在传送一个或多个数据块的开始和结束时,才需CPU干预
  • 通道控制方式
    • I/O通道控制方式是一种以内存为中心,实现外设与内存直接交换数据的控制方式
    • 与DMA方式相比,通道所需要CPU干预更少, 每次可以完成多个不连续的数据块传送,而且可以做到一个通道控制多台设备,从而进一步减轻了CPU的工作
    • I/O通道具有自己的指令系统,并能实现指令所控制的操作,由CPU发出启动指令启动
    • 通过执行通道程序并与设备控制器共同实现对I/O设备的控制

缓冲

引入原因

  • 缓和CPU与I/O设备间速度不匹配的矛盾
  • 提高CPU和I/O设备之间的并行性
  • 减少CPU对I/O的干预,减少对CPU的中断频率, 放宽对CPU中断响应时间的限制

缓冲实现机制

  • 单缓冲区
  • 双缓冲区
  • 环缓冲区
  • 缓冲池
    • 对多个缓冲区的管理
    • 收容输入、提取输入、收容输出、提取输出

设备独立性

  • 逻辑设备与物理设备无关

SPOOLING(假脱机系统)

  • 组成
    • 输入井/输出井
    • 输入缓冲区/输出缓冲区
    • 输入进程/输出进程
  • 当用户进程请求打印时, SPOOLing打印机系统为它做两件事:
    • 在输出井中为之申请一个空闲磁盘分区, 并将要打印的数据送入其中
    • 再为用户进程申请一张空白的用户请求打印表,并将用户的打印要求填入其中, 再将该表挂到打印请求队列上
    • 打印机空闲时:输出进程取出一张打印请求表,再从输出井中取出打印数据到输出缓冲区,通过打印机进行打印

十 文件系统

文件的逻辑结构

  • 有结构文件(记录式文件)
    • 顺序文件
    • 索引文件
    • 索引顺序文件
    • 直接文件/哈希文件
  • 无结构文件(流式文件)

文件的目录结构

  • 单级目录结构
  • 两级目录结构:系统目录+用户目录
  • 树形目录结构:在两级目录的基础上,允许用户自行添加子目录
  • 无环图目录结构:同一文件和子目录可出现在不同目录中
    • 别名问题、悬挂指针问题
  • 通用目录结构:允许存在环

文件共享

  • 基于索引节点的共享方式
    • 设置索引节点,存储文件的物理地址、链接计数(共享计数)及其它文件属性
    • 文件目录只包括文件名和该文件对应索引节点的指针
  • 利用符号链实现文件共享
    • 假设B为了共享C的文件F,在B中创建一个Link类型的新文件,新文件目录中只包含被链接文件F的路径名,称这种链接方法为符号链接(symbolic Linking)
    • 说明:只有文件主人的目录中有文件索引节点的指针,其它用户目录中只有路径名

文件保护措施:存取控制

  • 访问矩阵

文件的物理结构

  • 连续文件
  • 链接文件
  • 索引文件

空闲空间管理

  • 空闲表法
  • 位向量
  • 空闲块链

十一 磁盘管理

磁盘的访问时间

  • 数据传输时间、平均旋转延迟时间、寻道时间

磁盘调度算法

  • 先来先服务(FCFS)
  • 最短寻道优先(SSTF)
  • 扫描算法(SCAN、电梯算法)
  • 循环扫描(C-SCAN)
  • LOOK/C-LOOK(不扫描到终点,到最远的进程就马上掉头)
  • FSCAN:在扫描的过程中所有新产生的序列放在另外的一个队列中,当访问完当前队列之后,再访问新产生的一个队列;队列按SCAN算法处理

廉价磁盘冗余阵列RAID

并行交叉存取:

  • 有多台磁盘驱动器,系统将每一盘块中的数据分为若干个子盘块数据,再把每一个子盘块的数据分别存储到各个不同磁盘 中的相同位置上
  • 当要将一个盘块的数据传送到内存时,采取并行传输方式,从而减少传输时间