自己实现一个简单系统调用的流程如下:
- 在arch/arm/include/uapi/asm/unistd.h 头文件中增加一项
- 在 arch/arm/include/asm/unistd.h 头文件中修改全局变量
- __NR_syscalls,__NR_syscalls 表示一共有多少的系统调用
- 在 arch/arm/kernel/calls.S 汇编中增加函数接口
- 在 arch/arm/kernel/sys_arm.c 文件中实现函数
实现了系统调度之后,可以使用syscall和sysret来调用该系统调用,具体的步骤如下:
- syscall使执行逻辑从用户态切换到内核态,在进入到内核态之后,cpu会从 MSR_LSTAR寄存器中,获取处理系统调用内核代码的起始地址,即上面的 entry_SYSCALL_64。
- 在执行 entry_SYSCALL_64 函数时,内核代码会根据约定,先从rax寄存器中获取想要执行的系统调用的编号,然后根据该编号从sys_call_table数组中找到对应的系统调用函数。
- 接着,从 rdi, rsi, rdx, r10, r8, r9 寄存器中获取该系统调用函数所需的参数,然后调用该函数,把这些参数传入其中。
- 在系统调用函数执行完毕之后,执行结果会被放到rax寄存器中。如果用户程序需要该系统调用的返回结果,则从rax中获取。
- 最后,执行sysret汇编指令,从内核态切换回用户态,用户程序继续执行。