1 中断处理程序
1.1 以x86架构为例
在int80
中断处理程序中, 根据系统调用号, 调用系统调用表中对应的系统调用
大于等于4.17内核时, 所有的系统调用都只使用一个参数struct pt_regs
, 该参数中保存了处理器状态和中断发生时相关寄存器的值, 系统调用具体的参数就保存在寄存器中
do_syscall_64()
|-> regs->ax = sys_call_table[nr](regs);
小于4.17时系统调用使用6个参数, 其实就是把struct pt_regs
中存放系统调用参数的寄存器值传给了具体的系统调用
do_syscall_64()
|-> regs->ax = sys_call_table[nr](regs->di, regs->si, regs->dx,
regs->r10, regs->r8, regs->r9);
可以看到, 不管是哪个系统调用, 在中断处理程序中调用系统调用时传入的参数都一样(尽管每个系统调用的参数不尽相同), 具体的分析可以参考这篇文章
2 系统调用表
2.1 系统调用表的初始化
x86的系统调用表定义在/arch/x86/entry/syscall_64.c
中, 初始化过程也很简单, 就是把系统调用的函数赋值给系统调用表对应的项中, 最终,sys_call_table数组中的每个元素都将指向对应的系统调用函数
asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
[0 ... __NR_syscall_max] = &sys_ni_syscall,
[1] = sys_write,
[2] = sys_open,
[3] = sys_close,
};
2.2 系统调用号和系统调用的名字
不同架构的系统调用号可能不一样, 例如x86
__SYSCALL_COMMON(1, sys_write, sys_write)
__SYSCALL_COMMON(2, sys_open, sys_open)
__SYSCALL_COMMON(3, sys_close, sys_close)
__SYSCALL_COMMON(4, sys_newstat, sys_newstat)
__SYSCALL_COMMON(5, sys_newfstat, sys_newfstat)
arm64
#define __NR_read 63
__SYSCALL(__NR_read, sys_read)
#define __NR_write 64
__SYSCALL(__NR_write, sys_write)
#define __NR_readv 65
__SC_COMP(__NR_readv, sys_readv, compat_sys_readv)
#define __NR_writev 66
__SC_COMP(__NR_writev, sys_writev, compat_sys_writev)
#define __NR_pread64 67
__SC_COMP(__NR_pread64, sys_pread64, compat_sys_pread64)
#define __NR_pwrite64 68
__SC_COMP(__NR_pwrite64, sys_pwrite64, compat_sys_pwrite64)
3 具体系统调用的实现
可以参考这篇文章
4 compat兼容系统调用
compat
系统调用是为了向后兼容旧版Linux内核而设计的一组系统调用,可以在较新的Linux内核上运行旧版应用程序。这些系统调用具有与旧版Linux内核相同的接口和语义,使得旧版应用程序可以在新版Linux内核上运行而无需进行修改。
大多数的compat
系统调用都是直接使用正常的系统调用, 个别的系统调用需要把参数转换一下
具体可以参考这篇文章
参考资料
https://elixir.bootlin.com/linux/v4.19.275/source/arch/x86/entry/syscall_64.c
https://elixir.bootlin.com/linux/v4.2.8/source/include/uapi/asm-generic/unistd.h#L200
https://elixir.bootlin.com/linux/v4.19.274/source/arch/x86/entry/common.c#L293
https://elixir.bootlin.com/linux/v4.19.274/source/arch/x86/entry/entry_64.S#L242
https://elixir.bootlin.com/linux/v4.16.18/source/arch/x86/entry/common.c#L269
ARM64系统中兼容系统调用表compat_sys_call_table的定义和初始化
简要分析Linux 4.19内核ARM64架构系统调用(syscall)的定义
gcc x86_64中调用函数时多传了几个参数会发生什么