操作系统 Lab 3:进程、异常与调度
实验要求
实验指导书列出的实现任务为:
- 完成
env_init、map_segment、env_setup_vm与env_alloc。 - 完成
load_icode_mapper、load_icode与env_create,建立并装载用户进程。 - 完成
env_run。 - 补充
kern/entry.S、kernel.lds与RESET_KCLOCK。 - 完成
schedule。
Thinking 3.1:页目录自映射
解释:
e->env_pgdir[PDX(UVPT)] =
PADDR(e->env_pgdir) | PTE_V | PTE_PLV | PTE_C;
查看我当时的实验报告
这行代码把页目录中虚拟地址 UVPT 对应的页目录项,设为当前进程页目录所在物理页的页号,并附加有效位与访问属性。这样程序可以通过固定虚拟地址读取二级页表和页目录。
Thinking 3.2:elf_load_seg 的 data
elf_load_seg 以函数指针形式接收回调 map_page。找到 data 参数的来源,说明其作用,以及能否省略。
查看我当时的实验报告
data 来自创建进程时取得的新进程控制块指针。它让 load_icode_mapper 得到当前进程控制块,不能省略,否则回调无法知道要把 ELF 内容映射到哪个进程。
Thinking 3.3:段加载的边界情况
结合 elf_load_seg 的参数与实现,说明它需要处理哪些页面加载情况。
查看我当时的实验报告
先处理传入起始地址到页面边界之间的非对齐部分;随后逐页读入文件内容;最后对文件内容之外、内存段范围之内的部分补零。
Thinking 3.4:env_tf.era 中的地址
env_tf.era 保存的是物理地址还是虚拟地址?
查看我当时的实验报告
虚拟地址。
Thinking 3.5:异常处理函数
找出 0、1、4、11 号异常处理函数的实现位置。
查看我当时的实验报告
0 号异常处理函数 handle_int 在 genex.S 中定义;1 号 handle_tlb、4 号 handle_mod 和 11 号 handle_sys 由 genex.S 中的 BUILD_HANDLER 宏生成。
Thinking 3.6:时钟中断的开关
阅读 entry.S、genex.S 和 env_asm.S,说明时钟中断何时开启、何时关闭。
查看我当时的实验报告
就这三段代码而言,只在执行 ertn 返回时重新开启,中断处理的其余过程保持关闭。
Thinking 3.7:时钟中断如何切换进程
说明操作系统如何根据时钟中断切换进程。
查看我当时的实验报告
时钟中断触发异常,异常入口保存现场并分发到时钟中断处理程序;处理程序进入调度函数,判断是否需要选择新进程、设置新的时间片计数,再由进程运行函数切换上下文并恢复现场。
我当时记录的难点与体会
查看我当时的实验报告
我当时把难点概括为两条:一是中断与异常的完整链路——异常分发、处理与现场恢复;二是时钟中断或主动调度如何进入调度器、判断是否切换进程、重置计数并运行新进程。我第一次实现时很迷茫,熟悉完整流程后才逐渐能够把各段代码串起来。