xv6-k210/doc/内核原理-系统调用.md

4.1 KiB
Raw Permalink Blame History

System Call

System Call即系统调用以下简称syscall用于在用户程序中执行一些特权模式下才能完成的操作如I/O操作。 对于处理器而言syscall是一种同步发生的事件在基于RISC-V的操作系统中由ecall指令Environment Call产生。 当系统调用事件结束后处理器将返回到ecall指令的下一条指令继续执行。

原版xv6的文档将“system call”、“exception”和“interrupt”统称为“trap”。这可能与我们平常使用的术语有一定出入需要注意。 在RISC-V指令集手册的1.6节中对“exception”、“interrupt”和“trap”的定义是这样的

We use the term exception to refer to an unusual condition occurring at run time associated with an instruction in the current RISC-V hart. We use the term interrupt to refer to an external asynchronous event that may cause a RISC-V hart to experience an unexpected transfer of control. We use the term trap to refer to the transfer of control to a trap handler caused by either an exception or an interrupt.

从这个角度来看trap在RISC-V的语境下指的是控制权的转换也就是特权级的转换。

在RISC-V中请求系统调用

在RISC-V的用户程序中使用ecall指令请求syscall。操作系统提供不同功能的syscall对应不同的请求调用号。 因此请求前,需要向a7寄存器中写入所请求的syscall的调用号。以下为一个请求8号调用的例子

li  a7, 8
ecall

系统调用的处理过程

Syscall涉及到特权态的转换需要经过trap过程。对于用户程序而言一般是从用户模式U模式陷入到监管模式S模式。 我们知道操作系统中有中断向量表保存着各类异常与中断的处理例程的入口syscall的处理例程自然也在其中。 而对于不同类型的调用请求syscall的处理例程也有相应的系统调用表保存不同类型的系统调用功能函数的入口。 根据用户事先写入寄存器的系统调用号syscall的处理例程调用相应的功能函数完成系统调用随后返回至原先的特权态。

那么,执行ecall指令后,系统中发生了什么呢?其实不仅是系统调用,异常与各类中断发生后,首先都会经过这一过程——特权态的转换。 在RISC-V中各个特权级都有一组状态与控制寄存器CSRs当在U模式下中断发生时除了时钟中断RISC-V硬件系统会自动完成下列操作

  1. 如果发生的是设备中断,且sstatus寄存器的SIE位为0即中断关闭则不继续下列的操作也就是暂时忽略这个中断
  2. 关闭外部设备中断,即将sstatus寄存器的SIE位设为0
  3. 拷贝pc寄存器的值至sepc寄存器;
  4. 保存当前的特权态信息至sstatus寄存器的SPP字段;
  5. 设置scause寄存器其值表示trap产生的原因
  6. 将特权态设置为S模式
  7. stvec寄存器的值存入pc寄存器(stvec寄存器存放S模式的中断处理函数的入口地址
  8. 从新的pc值指向的指令继续执行。

执行上述步骤后处理机就进入了S模式。此时操作系统可能还需要进行一些额外操作以应对S模式下再次发生trap事件。 之后,根据scause寄存器,判断发生的是异常、中断或是系统调用,并进行相应的处理。处理完毕后,就执行sret指令返回U模式。 sret指令会执行若干相反的操作,例如将sepc的值写回pc、更新sstatus寄存器的SIE字段等使处理机恢复到原本U模式的执行状态。



参考文档