多道任务和分时系统
栈分配
假设当前有两个任务 A, B
, 考虑 2 种情况,A
可能从用户态切换到 B
,也可能从内核态切换过去
为了保存上下文,显然应该为每个任务都分配一个内核栈和用户栈
上下文的保存
由于程序的栈之间独立,所以只要栈指针(寄存器)指向了正确位置,就等于恢复了内存上下文
所以保存寄存器,就等于保存上下文
__swith
函数被用来切换上下文,riscv 中的 callee
寄存器有且只有 ra, sp, s0-s11
这 14
个寄存器,应当在 __swith
的汇编实现中手动保存
调用 __swtch
时,编译器会自动将 caller
寄存器保存到栈
任务切换
将内核态看作黑盒,所有程序都可以视作完全在用户态上完成
任务上下文需要保存三个东西:
ra
任务当前指令地址,以便恢复执行sp
任务当前栈指针,以便恢复状态- 其他寄存器
其实这三者都是通用寄存器
参考之前的批处理系统,任务刚开始时应该从 __restore
执行,假装自己刚从哨兵用户态 trap
到内核态,正打算回到用户态
因此 ra = __restore
, sp=kernel_stack
其他寄存器很合理地设为 0
变化
第二章中,__restore
需要手动 mv sp a0
,这是因为第一次运行时需要手动将栈从机器栈切换到内核栈
这一章中,第一次 __switch
时已经作此切换,__restore
中这一句可以删去