外观
综合复习:用执行路径、不变量和反例验收理解
下面的问题连接多个章节。先遮住答案,在纸上画路径并指出源码入口。每题至少回答“正常情况怎样工作、边界怎样处理、错误实现会出现什么症状”。仅能说出术语,还没有达到修改内核所需的程度。
题一:同一条用户写指令的三种命运
用户向地址 A 写入一个字节。A 分别位于未分配的合法 heap 页、COW 页、只读文本页。硬件表面上都可能报告 store page fault,内核如何区别?
展开分析
先根据地址范围与 VMA/进程大小判断语义,再看 PTE 是否存在及权限。合法 heap 洞可分配清零页;有效 COW 页可分配副本并保留其他进程映射;普通只读文本不应获得写权限,进程应被终止。2025 vmfault 已含 lazy 分配,扩展 COW 要先处理已有映射,再保留原有逻辑。成功修复后重试原指令,不增加 epc。
题二:fork、read、exit 的所有权账本
父进程的一页缓冲区 P 含 ABC。fork 后子进程调用 read 把 XYZ 读到该缓冲区,随后父先退出、子后退出。列出物理页数与引用变化。
展开分析
fork 后双方只读 COW 映射 P,引用为 2。read 的内核 copyout 必须解除子映射的 COW,分配 Q 并先复制原页,再写 XYZ;P=1,Q=1。父退出并经相应资源回收后 P 归零;子回收后 Q 归零。若 copyout 直接写 P,父读到 XYZ;若父释放时不看引用,子会访问被回收页。这里还要区分 kexit 成为 ZOMBIE 与 kwait/freeproc 回收用户内存的具体时机。
题三:少存一个寄存器会怎样
alarm handler 运行后,程序通常正常,却在某个整数计算测试中失败。程序没有非法地址访问。为什么仍然可能是内核错误?
展开分析
中断落在任意指令边界,所有活跃寄存器都属于被打断状态。若未恢复临时寄存器或 a0,程序会继续执行合法指令,但输入值已改变,因此得到错误计算。sigreturn 经过通用分派写回 a0,也是常见的二次覆盖。验证不仅看是否回到原 PC,还要比较完整用户寄存器快照。
题四:两种看似相同的“等待”
一个线程等待队列非空,另一个等待自旋锁释放。为什么不能都写成 while 循环忙等?
展开分析
短临界区可忙等,但等待 I/O 或生产者可能持续很久,应让出 CPU。队列等待还需要检查条件与进入睡眠的原子交接,避免丢失唤醒。持自旋锁时睡眠又可能阻碍完成条件的生产者,因此需明确哪些锁只保护状态、哪些操作可阻塞。wakeup 不是资源所有权转移,醒后必须重新检查条件。
题五:给出一个能击穿错误大页实现的例子
某实现通过了“分配 2MiB 并写第一页”,但没有真正支持大页。如何用最小场景暴露问题?
展开分析
在相隔 4KiB 的位置写不同值并读回,可暴露把大页内部偏移丢弃的 walkaddr/copy 路径。释放末尾 4KiB,再读取前一页,可暴露缺少 demotion 或错误整块释放。fork 后分别修改父子最后一页,可暴露只复制前 4KiB 或错误共享。检查物理页回收还需重复创建与销毁。
题六:链接、描述符与映射的身份
一个文件已被 mmap,随后关闭 fd 并删除原路径。映射是否应立即成为悬空指针?这与符号链接有何不同?
展开分析
VMA 持有 file 引用,关闭用户 fd 只减少对应引用;删除名称也不应直接销毁仍被引用的文件对象。后续缺页仍可按持有 inode 读取。符号链接保存路径,之后解析时依据当时的命名空间;目标路径删除会使跟随失败。一个是对象引用生命周期,一个是延迟路径解析,不能混为一谈。
题七:为什么 read-write lock 不只是 readers 计数
实现允许多个读者,且写者只有 readers=0 时进入。系统持续有读请求时,写者仍可能永久等待。如何解释并修复?
展开分析
新读者不断在旧读者退出前进入,readers 永远不归零。应登记等待写者,阻止后来的读者插队;登记与进入判断需同步。等待计数每个写者只增一次,成功进入时减一次。该政策解决读者淹没写者,不自动提供 FIFO 或读者无饥饿,报告公平性时要准确。
最后的实作验收
不用打开本课程正文,画出 write → syscall → 文件系统 → 日志 → 驱动;再画出 fork → COW → copyout → 回收。任选一条路径,在真实固定分支中找到所有主要函数,并给每个资源标注创建、共享、释放点。
然后做一次“小改动—预测—验证”:例如在教学模型中故意让 fork 不清父 writable,先预测哪项测试失败,再运行并解释结果。修改后恢复模型。能提前预测失败说明你掌握了机制;只会看最终报错仍需要回到不变量。
本课程完成标准是能够独立解释这些路径并完成九个实验验收,而不是背下所有函数。进一步学习 Linux 时,可沿相同问题找更复杂的实现:多线程地址空间、TLB shootdown、页缓存、NUMA、生产文件系统恢复,都能接在这套基础上。
来源范围:2025 官方教材和本课程各实验页;以上题目及分析为围绕固定版本编写的综合练习。