操作系统可视化

操作系统让多个程序共享机器。本组课程展示四项工作:选择下一个运行的进程、把虚拟地址映射到物理内存、通过路径找到文件数据、协调线程对共享变量的访问。代码与动画逐步同步,可以看到短任务先运行、占用 CPU 的进程被降级、缺页触发磁盘读取,以及删除文件名后数据仍留在磁盘上。

进程使用处理器、地址空间和文件名,背后却是多人共享的资源。操作系统负责维持这些抽象与底层状态的一致性。

共享 CPU

可运行进程的数量可能超过处理器数量。调度器选择谁先运行,吞吐量、响应速度和公平性会要求不同的选择。

每项策略都要回答两个问题:

  • 选谁? 按到达顺序、任务长度、轮转顺序,或根据进程行为调整的优先级。
  • 能否抢占? 非抢占策略让进程运行到阻塞或结束;抢占策略可在运行中收回 CPU,提高响应速度,也增加上下文切换成本。

选择规则与抢占规则共同影响等待时间、饥饿风险和交互体验。

策略选择依据抢占取舍
FCFS到达顺序否实现简单,但长任务让后续任务等待,形成护航效应
SJF最短 CPU 执行段否在任务已就绪且长度已知等条件下减少平均等待;长任务可能饥饿
时间片轮转固定时间片,循环分配是提供轮转机会;时间片长度影响响应延迟与切换开销
MLFQ动态优先级,占用 CPU 的任务降级是不预知任务长度,通过反馈近似短任务优先

FCFS 按先来后到服务,但不能避免长任务造成等待。SJF 需要任务长度,且可能让长任务长期等待。轮转强调响应,不区分任务长度。MLFQ 观察行为,再调整优先级,组合这些策略的思路。

共享内存

程序使用虚拟地址。访问内存时,硬件把地址拆成页号与页内偏移,查出对应物理帧,再保留原偏移组成物理地址。

本课用数量级模型展示三条路径:TLB 缓存命中约一个周期,访问内存中的页表约一百个周期,页不在内存、需要磁盘读取时约一百万个周期。数字用于对比成本,不代表所有硬件的固定时延。本课缺页路径会进入内核并读盘;实际系统也有无需磁盘读取的缺页。等待期间,内核可以调度其他进程,地址转换由此与 CPU 调度相连。

RAM 已满时,还要选择页面置换的受害页。FIFO 记录装入时刻;LRU 每次访问都更新最近使用时刻;Clock 维护引用位,用旋转指针清除和检查它。同样三个帧、十二次访问,策略差异可造成两次磁盘访问的差距。引用位提供了成本较低的近期访问线索。

策略每帧记录淘汰对象局限
FIFO装入时的访问序号最早装入的页忽略后续命中,可能淘汰热页;增加帧数也可能增加缺页,即 Bélády 异常
LRU最近访问序号最久未访问的页循环访问的页数比帧数多一时,可能每次都缺页
Clock一个引用位扫描中遇到的引用位为 0 的页所有位为 1 时会先清除一轮,本课对应状态的淘汰顺序呈 FIFO 特征

磁盘上的名字与数据

文件系统把名字和文件记录分开。本课中,inode 保存类型、大小、链接数和数据块编号;父目录的数据项把文件名映射到 inode 编号。

由此可以算出路径解析成本。在本课无缓存模型中,每经过一级目录要读目录 inode 和目录数据。打开 /home/user/notes.txt 要先读七次,才开始读取文件内容;文件大小不影响这七次路径查找。

rm 修改父目录并减少链接数。在本模型没有其他存活引用的情况下,链接数归零才释放数据块。硬链接仍存在时,文件数据仍可访问;即使块已释放,也不表示原字节被覆写。实际系统还需考虑打开的文件句柄等引用。

共享变量

同一进程中的线程共享内存。本课把 counter = counter + 1 拆成 load、add、store 三步。若两线程在中途切换,可能都读取同一个旧值,后一次写入覆盖前一次增量。计算和写入均已执行,却没有得到两次递增。

互斥锁让遵守同一锁协议的线程互斥访问临界区。它不禁止调度器抢占,而是让另一个线程等待锁,避免进入同一受保护操作。本课会丢失两次更新的调度,在加锁后保留全部更新。

锁也有风险:两个线程按相反顺序获取两把锁,各自持有一把再等待另一把,就会死锁。

建议学习顺序

先学进程调度。相同任务分别运行 FCFS、SJF 和时间片轮转。保持工作负载不变,比较 FCFS 的长任务阻塞、SJF 的饥饿风险和轮转的响应方式。

再学 MLFQ 调度。任务从高优先级开始,用尽 CPU 配额后降级。不必预先知道运行时长,也能根据行为近似短任务优先。

接着学虚拟内存。追踪地址拆分、TLB 查询、页表遍历、缺页和磁盘读取。结尾的成本条中,三次读盘占据大部分宽度,地址转换只占窄条。无效地址场景则在页表中找不到映射,展示本课的段错误路径。

然后学页面置换。虚拟内存课的 RAM 不会填满,本课从 RAM 已满开始。对同一引用序列运行 FIFO、LRU、Clock,比较缺页数。再试两个反例:FIFO 增加到四帧后缺页更多;LRU 用三帧循环访问四页,十二次访问全部缺页。

再学文件系统。查看位图、inode 表和数据块指针,理解由名字驱动的查找,以及删除名字时链接计数的作用。

线程与同步可在进程调度之后学习。默认运行预期计数 6,竞争后只剩 4;CPU 时间轴标出两次更新丢失的位置。随后加锁,对比结果,再用相反锁顺序制造死锁。

全部操作系统课程

打开下方课程,修改工作负载或访问序列,逐步查看时间轴,并核对同步高亮的代码。