Thinking

Thinking 3.1

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

A:使得env_pgdir对应的二级页表结构中虚拟地址UVPT对应存储一级页表地址

Thinking 3.2

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

A:data在此处的来源为load_icode,也就是进程控制块的指针。不可以没有这个参数。如果没有,回调函数中无法通过进程控制块获取页目录地址以及asid。

Thinking 3.3

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

A:需要考虑以下特殊情况:

  • 目标虚拟地址va不是页对齐的
  • 被拷贝文件大小bin_size不是页对齐的
  • sgsize>bin_size即内存大小大于文件大小
  • 内存大小sgsize不是页对齐的

Thinking 3.4

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

A: env_tf.cp0_epc存储的是虚拟地址

Thinking 3.5

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

A: 0,1,2,3号异常均是在kern/genex.S中实现

Thinking 3.6

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

A:

1
2
3
4
5
6
.section .text.exc_gen_entry
exc_gen_entry:
...
and t0, t0, ~(STATUS_UM | STATUS_EXL | STATUS_IE)
mtc0 t0, CP0_STATUS // 在进入异常处理程序时候关中断
...
1
2
3
FEXPORT(ret_from_exception)
RESTORE_ALL // 在离开异常处理程序前,在RESTORE_ALL宏中恢复status寄存器
eret

Thinking 3.7

阅读相关代码,思考操作系统是怎么根据时钟中断切换进程的。

A:当时钟中断发生时候,会执行schedule函数,使得当前进程的时间片计数count减1,当count为0或者当前进程被阻塞时候进行进程切换。以上过程即根据时钟中断切换进程。

难点分析

对我来说,此次实验的难点是时钟中断的处理流程:

主要如下:

  • **进入异常分发处理代码entry.S**在其中实现状态保存和根据Exccode跳转到对应的异常处理程序
  • 跳转到exception_handlers中关于处理中断的函数handle_int
  • 根据Cause寄存器的中断位判断是几号中断,进入对应的中断处理函数中(genex.S),在这里我们进入timer_irq
  • timer_irq调度schedule(sched.c)函数,完成进程切换

实验感悟

在lab3中,我们主要完成了进程管理的初始化,进程创建和进程切换三个大的任务。

  • 进程管理初始化主要在env_init的初始化,其中对进程控制块的管理与lab2中的页控制块管理异曲同工
  • 进程创建主要包括env_create,env_alloc,load_icode三者
  • 进程切换通过时钟中断机制实现,包括异常处理函数部分与scheduleenv_run函数

此次实验的课下部分需要我们实现的不是很多,且各个函数之间的连接关系紧密且关系明确,没有lab2中那么多的宏那样让人头大,为我们降低很多难度。

OS的学习可能首先还是要理清各个函数的功能以及其之间的调用关系,能够在心中形成一张清晰的脉络图,之后再去深究每个函数的实现细节,这样学习起来对实验的理解可能会更深一点