4.3 代码:调用系统调用

第2章以initcode.S调用exec系统调用(user/initcode.S:11)结束。让我们看看用户调用是如何在内核中实现exec系统调用的。

用户代码将exec需要的参数放在寄存器a0a1中,并将系统调用号放在a7中。系统调用号与syscalls数组中的条目相匹配,syscalls数组是一个函数指针表(kernel/syscall.c:108)。ecall指令陷入(trap)到内核中,执行uservecusertrapsyscall,和我们之前看到的一样。

syscallkernel/syscall.c:133)从陷阱帧(trapframe)中保存的a7中检索系统调用号(p->trapframe->a7),并用它索引到syscalls中,对于第一次系统调用,a7中的内容是SYS_execkernel/syscall. h:8),导致了对系统调用接口函数sys_exec的调用。

当系统调用接口函数返回时,syscall将其返回值记录在p->trapframe->a0中。这将导致原始用户空间对exec()的调用返回该值,因为RISC-V上的C调用约定将返回值放在a0中。系统调用通常返回负数表示错误,返回零或正数表示成功。如果系统调用号无效,syscall打印错误并返回-1。