ser/usys.S 中用于 xv6 os 的系统调用程序集
syscall assembly in ser/usys.S for the xv6 os
在user/usys.S
这里有一个由usys.pl script
生成的片段
.global sbrk
sbrk:
li a7, SYS_sbrk
ecall
ret
.global sleep
sleep:
li a7, SYS_sleep
ecall
ret
.global uptime
uptime:
li a7, SYS_uptime
ecall
ret
用户函数需要调用内核系统调用,因为只有内核才有权限执行所需的指令。
所以用户函数需要写成汇编,这样才能使用riscv ecall
指令触发内核函数。
如何将参数传递给此内核系统调用函数?
我们就来说说sleep
吧。在您之前的一个问题中,您将 link 发布到 user.h header file。
该头文件告诉您的 C 编译器函数采用什么参数以及函数 returns,在这一行:
int sleep(int);
处理该行后,C 编译器知道 sleep
需要单个 int
参数。因此,当您尝试在 C 程序中调用该函数时,编译器将确保使用向您平台上的函数传递 int
参数的标准方式将参数传递给该函数。这叫做calling convention。例如,调用约定可能会说将参数放入堆栈或将其放入特定寄存器。您可以查看 C 编译器生成的程序集,了解它在调用 sleep
.
时做了什么
我真的不知道 ecall
做什么的细节,但在某些时候它应该会触发你内核中的一些代码,并且这些代码也会知道你的平台的调用约定,所以它可以检索您的 C 编译器传递给 sleep
.
的参数
有关内核端的更多详细信息,请查看 the source code of sys_sleep 并了解它如何调用 argint
来获取其参数。
在user/usys.S
这里有一个由usys.pl script
.global sbrk
sbrk:
li a7, SYS_sbrk
ecall
ret
.global sleep
sleep:
li a7, SYS_sleep
ecall
ret
.global uptime
uptime:
li a7, SYS_uptime
ecall
ret
用户函数需要调用内核系统调用,因为只有内核才有权限执行所需的指令。
所以用户函数需要写成汇编,这样才能使用riscv ecall
指令触发内核函数。
如何将参数传递给此内核系统调用函数?
我们就来说说sleep
吧。在您之前的一个问题中,您将 link 发布到 user.h header file。
该头文件告诉您的 C 编译器函数采用什么参数以及函数 returns,在这一行:
int sleep(int);
处理该行后,C 编译器知道 sleep
需要单个 int
参数。因此,当您尝试在 C 程序中调用该函数时,编译器将确保使用向您平台上的函数传递 int
参数的标准方式将参数传递给该函数。这叫做calling convention。例如,调用约定可能会说将参数放入堆栈或将其放入特定寄存器。您可以查看 C 编译器生成的程序集,了解它在调用 sleep
.
我真的不知道 ecall
做什么的细节,但在某些时候它应该会触发你内核中的一些代码,并且这些代码也会知道你的平台的调用约定,所以它可以检索您的 C 编译器传递给 sleep
.
有关内核端的更多详细信息,请查看 the source code of sys_sleep 并了解它如何调用 argint
来获取其参数。