思考题

Thinking 3.1

请结合 MOS 中的页目录自映射应用解释代码中 e->env_pgdir[PDX(UVPT)] = PADDR(e->env_pgdir) | PTE_V 的含义。

  • e->env_pgdir 代表当前进程的页目录的基地址。在 MOS 中,每个进程都有自己的页目录,用于存储该进程的页表信息。
  • PADDR(e->env_pgdir) 代表这个函数获取页目录的物理地址。PADDR是一个宏,用于将内核虚拟地址转换为物理地址。
  • PTE_V :这是一个标志位,表示页表项有效。PADDR(e->env_pgdir) | PTE_V,表示给页目录的物理基地址加上权限位。
  • PDX(UVPT):这是一个宏,用于获取虚拟地址 UVPT 的页目录索引。

所以,这行代码的作用是将当前进程的页目录的物理地址映射到用户虚拟地址空间的UVPT地址处,并设置页表项为有效。这样,进程就可以在自己的地址空间中访问页表和页目录,提高了访问效率。

Thinking 3.2

elf_load_seg 以函数指针的形式,接受外部自定义的回调函数 map_page。 请你找到与之相关的 data 这一参数在此处的来源,并思考它的作用。没有这个参数可不可以?为什么?

elf_load_seg 函数中,data 参数是一个指向用户自定义数据的指针,它将被传递给 map_page 回调函数。

load_icode 函数中,当调用 elf_load_seg 时,data 参数被设置为当前环境结构 struct Env *e 的地址。这样,在 map_page 回调函数中,可以通过 data 参数访问到当前环境的信息,例如页目录 env_pgdir 和地址空间标识符 env_asid,这些信息对于将页面插入到正确的进程地址空间至关重要。

因此,data 参数是必需的,它使得 elf_load_segmap_page 函数能够与调用者之间传递必要的数据。

Thinking 3.3

结合 elf_load_seg 的参数和实现,考虑该函数需要处理哪些页面加载的情况。

  • 处理程序段的虚拟地址 p_vaddr 没有对齐到页边界的情况,计算偏移量并实现对齐。
  • 在任何调用 map_page 的地方,如果 map_page 返回非零值,表示映射失败,elf_load_seg 函数都会立即返回这个错误值。
  • 如果段的内存大小 p_memsz 大于文件的尺寸 p_filesz,说明段在内存中比在文件中占据更多的空间。在这种情况下,需要额外分配页来填充这部分空间。

Thinking 3.4

思考上面这一段话,并根据自己在 Lab2 中的理解,回答:

  • 你认为这里的 env_tf.cp0_epc 存储的是物理地址还是虚拟地址?

虚拟地址。CP0中存储的EPC是CPU产生异常的指令地址,对于CPU来说,其所见的都是虚拟地址。

Thinking 3.5

试找出 0、1、2、3 号异常处理函数的具体实现位置。8 号异常(系统调用)涉及的 do_syscall() 函数将在 Lab4 中实现。

genex.S文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
NESTED(handle_int, TF_SIZE, zero)
mfc0 t0, CP0_CAUSE
mfc0 t2, CP0_STATUS
and t0, t2
andi t1, t0, STATUS_IM7
bnez t1, timer_irq
timer_irq:
li a0, 0
j schedule
END(handle_int)

BUILD_HANDLER tlb do_tlb_refill

#if !defined(LAB) || LAB >= 4
BUILD_HANDLER mod do_tlb_mod
BUILD_HANDLER sys do_syscall
#endif

Thinking 3.6

阅读 entry.Sgenex.Senv_asm.S 这几个文件,并尝试说出时钟中断在哪些时候开启,在哪些时候关闭。

  1. 异常处理。当发生异常的时候,会通过mfc0 t0, CP0_STATUSmtc0 t0, CP0_STATUS指令来修改CP0_STATUS来关闭中断
  2. 系统调用
  3. 当异常处理或系统调用完成后,会通过 ret_from_exception 标签返回。在这里,会执行 RESTORE_ALLeret 指令来恢复寄存器状态并返回到发生异常前的状态。
  4. 进程切换。

Thinking 3.7

  1. 通过时钟中断来触发异常
  2. 异常处理程序先确定是时钟中断,并调用调度函数
  3. 调度函数通过一定的调度算法,选择一个新的进程开始执行
  4. 操作系统执行上下文的切换,保存当前进程、恢复新进程的状态
  5. 返回,执行新进程

难点分析

本次的课下lab虽然内容有点多但是整体难度其实不高,毕竟跟着注释写就完事了,但是比较难的是我们要对新增的文件以及我们在这个lab干了什么做一个比较完整的把握。

相比较之前的lab,这次的lab比较注重和理论课的联系,把理论课上进程调度仔细学好,才能好好参加本次的exam。建议一定要通读新增文件的每个函数的Overview,无论是否要求自己补全的

实验体会

本次课下lab花费的时间不多,代码填空也没有很复杂的函数调用,所以仅仅完成课下任务是不行的,远不足以支撑我们完成限时测试。

另外,本次上机出现了一个令人难绷的bug,好在20:55的时候非常极限的找到并提交了,不得不说抗压能力是很重要的~