syscall表中的/ ptregs

时间:2017-03-05 14:02:19

标签: linux-kernel system-calls

为什么系统调用表中的某些系统调用具有/ptregs

来自arch/x86/entry/syscalls/syscall_64.tbl的例子:

54      64      setsockopt              sys_setsockopt
55      64      getsockopt              sys_getsockopt
56      common  clone                   sys_clone/ptregs
57      common  fork                    sys_fork/ptregs
58      common  vfork                   sys_vfork/ptregs
59      64      execve                  sys_execve/ptregs
60      common  exit                    sys_exit
61      common  wait4                   sys_wait4

1 个答案:

答案 0 :(得分:2)

这些是特殊的系统调用,需要在堆栈中布置完整的寄存器转储(作为struct pt_regs)。这只适用于64位x86架构,因为它有更多寄存器(与32位相比)。

系统调用处理程序(arch/x86/entry/entry_64.S:entry_SYSCALL_64)将大多数寄存器保存在系统调用条目上。这部分是为了支持ptrace()并部分地将参数传递给用C编写的实际系统调用处理程序(这就是为什么它们具有asmlinkage规范,它使得函数从堆栈获取参数)。系统调用最多有6个参数(rdi,rsi,rdx,r10,r8,r9),有些寄存器用于SYSCALL簿记(rax,rcx,r11)。您不需要保存rbp,rbx,r12,r13,r14,r15(因为它们是被调用者保存的),因此出于性能原因,它们不会保存在条目中。系统调用处理完成后,寄存器将从此备份恢复,然后返回用户空间。

但是,某些系统调用(如execve(),fork(),sigreturn()等)需要在堆栈中包含所有寄存器(包括rbp,rbx,r12-r15) ,在struct pt_regs。这是因为这些系统调用可能导致用户空间从其他地方重新开始执行,因此需要保存准确的寄存器值。它们在syscall_64.tbl中标有/ptregs,以便发生以下魔法。

通常,系统调用处理程序表(sys_call_table)包含指向C函数的指针。但对于那些特殊的系统调用,处理程序是small assembly thunks,它首先保存额外的寄存器,然后跳转到C代码(慢速路径就是这样)。表中的/ptregs后缀指示脚本将这些存根而不是C函数插入到处理程序表中。