Post

BUAA-OS-lab3

BUAA-OS-lab3

lab3 实验报告

思考题

Thinking 3.1

  • 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 函数中,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

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

Thinking 3.4

虚拟地址。EPC 是 cpu 出现异常时的指令地址,cpu 访问的地址都是虚拟地址。

Thinking 3.5

genex.S 文件中。

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 mod do_tlb_mod
BUILD_HANDLER sys do_syscall

Thinking 3.6

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

Thinking 3.7

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

实验难点分析

我认为 lab3 实验相对来说比较简单,其实就是管理进程块的一些信息。结合理论课的知识,理解进程块各个字段的作用之后,实现起来并不困难。

不过,虽然单个函数的作用和填充实现相对来说都便于理解,但是整个进程管理的架构还是比较复杂的,涉及到大量的函数和文件,需要对整个架构有一个比较清晰的认识,才能更好地理解进程管理的过程。

实验体会

这次的课下 lab 很快就完成了,需要填充的空不多,代码填空的地方也没有很灵活的函数调用应用。并且在完成的时候发现,甚至不太需要仔细阅读实验指导书,只需要根据代码注释,注释说什么就写什么就行了(bushi)。但显然,这样的课下任务量是远远不足以支撑我们完成课上测试的。

相较于工作量和思维量并不大的代码填空,一个星期的时间里,更重要的是通篇阅读新增的代码,阅读每个函数的 Overview 及其实现,掌握每个函数的作用、应用场景以及实现方式、相互调用的关系。

比如这次上机的 exam 题目,需要填充的代码行数并不多,但是在很多文件中都需要进行一些更改。这就对我们对总体架构的掌握程度有较高的要求,我们需要清楚每个文件里都有什么内容,在架构中起到什么作用,这样才能够在合适的地方添加代码。

另外,这次上机对于很多内容的不熟悉还暴露出了对知识点掌握不熟的问题。因为课下工作量小,且也没有其它渠道进行练习,许多基础的东西还停留在“会做但是不熟”的掌握程度,例如对一个虚拟地址的访存,在课上测试的时候还花费了不少时间才实现。

This post is licensed under CC BY 4.0 by the author.