Lab
-
lab2 中, 我们是什么时候第一次进入U态的?
在
__init_sepc中调用sret时. 因为程序一开始执行main函数, 到call_first_process时选择第一个进程, 进行一次__switch_to. 在退出时会进入__init_sepc中, 此时的SPP = 0, 调用sret会将特权级设成 U 态, 所以此时第一次进入 U 态.特别地, 执行
sret进入 U 态跳转到0x80200000, 即head.S中_start的位置. 此时执行call main后,main()的第一句puts()需要 S 态权限, U 态执行时会触发trap_s, 而sepc被设置为ecall指令的位置, 此时执行trap_s到handler_s, 由于不是时钟中断, 会跳到else分支, 如果里面加输出会看到程序输出; 之后回到trap_s,sret又回到ecall, 但是进入trap_s前是 U 态, 所以会一直在ecall指令重复进入trap_s, 达到死循环的目的; 前面的输出也会循环输出 -
lab2 中样例进入死循环的问题. 经过 GDB 调试, 发现倒数第二条样例最后一个完成的是第二个进程, 而在完成上一个样例时调用的是
task_init() + init_test_case() + schedule(), 由于schedule()没有初始化current, 所以current仍然指向pid = 2, 此时__switch_to将pid = 2进程保存在栈上的ra更新成现在的ra, 即__switch_to的下一行. 当调度算法运行到需要切换到pid = 2时, 从栈上恢复的ra为__switch_to的下一行, 即return. 所以出现了再一次执行return的情况, 导致程序出错. 解决方法: 将schedule()改成call_first_process(), 初始化current即可.