55 lines
4.1 KiB
Markdown
55 lines
4.1 KiB
Markdown
# 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 <u>*exception*</u> to refer to an unusual condition occurring at run time associated with
|
||
an instruction in the current RISC-V hart. We use the term <u>*interrupt*</u> 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 <u>*trap*</u> 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模式的执行状态。
|
||
|
||
<br>
|
||
<br>
|
||
|
||
# 参考文档
|
||
|
||
+ [*xv6: a simple, Unix-like teaching operating system*](https://pdos.csail.mit.edu/6.S081/2020/xv6/book-riscv-rev1.pdf)
|
||
+ [*The RISC-V Instruction Set Manual Volume I: Unprivileged ISA*](https://github.com/riscv/riscv-isa-manual/releases/download/draft-20210212-c879d5a/riscv-spec.pdf)
|
||
+ [《RISC-V手册——一本开源指令集的指南》](http://riscvbook.com/chinese/RISC-V-Reader-Chinese-v2p1.pdf) |