Skip to content

pa4-1

题目

1.详细描述从测试用例中的int $0x80开始一直到HIT_GOOD_TRAP为止的详细的系统行为(完整描述控制的转移过程,即相关函数的调用和关键参数传递过程),可以通过文字或画图的方式来完成;
  • 首先在int_指令中调用raise_sw_intr来间接调用异常处理函数raise_intr
  • raise_intr中保存状态,将eflags、cs、eip等进行压栈,然后从IDT表获取中断处理程序的信息,设置eip进行跳转,并切换内核态
  • kernel开始处理,根据idt初始化时的设置进行响应调用压栈等操作(do_irq.S进行处理),之后由asm_do_irq执行pusha保存寄存器信息,然后调用irq_handle进行处理
  • irq_handle首先从栈中提取栈中的数据(GPRs irq号 error_code eip cs eflags)并以结构体TrapFrame存储。之后根据系统调用号对内部异常、外部中断、int80系统调用进行分类处理。
  • 回到asm_do_irq,执行出栈以及popa等,并恢复存储的eip、cs、eflags等对原先的栈帧进行恢复,恢复到用户态继续执行系统调用前执行的程序,即到达HIT_GOOD_TRAP
2.在描述过程中,回答kernel/src/irq/do_irq.S中的push %esp起什么作用,画出在call irq_handle之前,系统栈的内容和esp的位置,指出TrapFrame对应系统栈的哪一段内容。
  • 用于对原先的esp进行保存,之所以在此处进行保存是因为之前的pusha保存了除esp之外的寄存器(因为esp会由于push改变,因此应该在所有其他数据都保存完成之后再push入栈)

  • image-20230701162204550

  • | ... | | ... | | eflags |--- | cs | | | eip | | | error_code | TrapFrame | irq | | | ... | | | GRPs |--- | esp |<-esp

3.详细描述NEMU和Kernel响应时钟中断的过程和先前的系统调用过程不同之处在哪里?相同的地方又在哪里?可以通过文字或画图的方式来完成。
  • 系统调用是通过int_指令引起的(详细见第一题),时钟中断是通过定时调用timer_intr从而调用i8259_raise_intr(TIMER_IRQ)来修改cpu.intr,而cpu每执行一条指令都会去调用do_intr(),会检查cpu.intr IF,并调用raise_intr(intr_no);来对时钟中断进行响应,这之后的过程与系统调用是一致的。
  • 即不同点主要体现在raise_intr(intr_no)的调用位置,是由程序主动调用,还是执行指令后检查时发现外部中断并进行调用

实验总结

  • 这阶段要写的代码不多,但是由于前面累计的问题太多,花了太多的时间,推进十分艰难。发现前面2-1的pop实现有问题、3-1的cache有问题,程序总是莫名其妙的出错,而且由于代码太长已经难以debug,只能一点点排查。
  • 感觉随着完成的部分越多,代码中潜在的问题也越多,大部分的时间并不是在写新的代码,而是在修补以前的代码,希望后面还能顺利完成。