多道任务和分时系统

栈分配

假设当前有两个任务 A, B, 考虑 2 种情况,A 可能从用户态切换到 B,也可能从内核态切换过去

为了保存上下文,显然应该为每个任务都分配一个内核栈和用户栈

上下文的保存

由于程序的栈之间独立,所以只要栈指针(寄存器)指向了正确位置,就等于恢复了内存上下文

所以保存寄存器,就等于保存上下文

__swith 函数被用来切换上下文,riscv 中的 callee 寄存器有且只有 ra, sp, s0-s1114 个寄存器,应当在 __swith 的汇编实现中手动保存

调用 __swtch 时,编译器会自动将 caller 寄存器保存到栈

任务切换

将内核态看作黑盒,所有程序都可以视作完全在用户态上完成

任务上下文需要保存三个东西:

  • ra 任务当前指令地址,以便恢复执行
  • sp 任务当前栈指针,以便恢复状态
  • 其他寄存器

其实这三者都是通用寄存器

参考之前的批处理系统,任务刚开始时应该从 __restore 执行,假装自己刚从哨兵用户态 trap 到内核态,正打算回到用户态

因此 ra = __restore, sp=kernel_stack

其他寄存器很合理地设为 0

变化

第二章中,__restore 需要手动 mv sp a0,这是因为第一次运行时需要手动将栈从机器栈切换到内核栈

这一章中,第一次 __switch 时已经作此切换,__restore 中这一句可以删去