`entry_SYSCALL64_slow_path` 和 `entry_SYSCALL64_fast_path` 的区别
The difference between `entry_SYSCALL64_slow_path` and `entry_SYSCALL64_fast_path`
我们知道系统调用会调用entry_64.S中的函数entry_SYSCALL_64
。看源码的时候,发现寄存器准备后的调用有两种,一种是entry_SYSCALL64_slow_path
,一种是entry_SYSCALL64_fast_path
。你能说出这两个函数的区别吗?
进入 entry_SYSCALL_64
Linux 将:
- 交换
gs
以获得每个 cpu 参数。
- 根据上面的参数设置堆栈。
- 禁用 IRQ。
- 在堆栈上创建一个partial
pt_regs
结构。这会保存调用方上下文。
- 如果当前任务设置了
_TIF_WORK_SYSCALL_ENTRY
或_TIF_ALLWORK_MASK
,则进入慢路径。
- 否则请输入快速路径。
_TIF_WORK_SYSCALL_ENTRY
被定义为 here,注释说明:
/*
* work to do in syscall_trace_enter(). Also includes TIF_NOHZ for
* enter_from_user_mode()
*/
_TIF_ALLWORK_MASK
似乎没有为 x86 定义,MIPS 的定义是 here,注释为:
/* work to do on any return to u-space */
快速路径
Linux 将:
- 启用 IRQ。
- 检查系统调用号是否超出范围(注意
pt_regs
结构已经用 ENOSYS
为 rax
的值创建)。
- 通过间接跳转调度到系统调用。
- 将系统调用的 return 值 (
rax
) 保存到堆栈上 pt_regs
中的 rax
。
- 再次检查当前任务是否设置了
_TIF_ALLWORK_MASK
,如果是则跳转到慢return路径.
- 恢复调用方上下文并发出
sysret
。
慢 return 路径
- 将之前没有保存的寄存器保存在
pt_regs
中(rbx
,rbp
,r12
-r15
).
- 调用
syscall_return_slowpath
,定义here.
请注意,第 2 点最终会调用 trace_sys_exit
。
慢路径
- 将之前没有保存的寄存器保存在
pt_regs
中(见上文)
- 调用
do_syscall_64
,定义here。
点 2 将调用 syscall_trace_enter
。
所以慢速与快速路径与 ptrace
有关。我没有深入研究代码,但我想如果调用者不需要 ptrace
,则整个机器都会被跳过。
这确实是一个重要的优化。
我们知道系统调用会调用entry_64.S中的函数entry_SYSCALL_64
。看源码的时候,发现寄存器准备后的调用有两种,一种是entry_SYSCALL64_slow_path
,一种是entry_SYSCALL64_fast_path
。你能说出这两个函数的区别吗?
进入 entry_SYSCALL_64
Linux 将:
- 交换
gs
以获得每个 cpu 参数。 - 根据上面的参数设置堆栈。
- 禁用 IRQ。
- 在堆栈上创建一个partial
pt_regs
结构。这会保存调用方上下文。 - 如果当前任务设置了
_TIF_WORK_SYSCALL_ENTRY
或_TIF_ALLWORK_MASK
,则进入慢路径。 - 否则请输入快速路径。
_TIF_WORK_SYSCALL_ENTRY
被定义为 here,注释说明:
/* * work to do in syscall_trace_enter(). Also includes TIF_NOHZ for * enter_from_user_mode() */
_TIF_ALLWORK_MASK
似乎没有为 x86 定义,MIPS 的定义是 here,注释为:
/* work to do on any return to u-space */
快速路径
Linux 将:
- 启用 IRQ。
- 检查系统调用号是否超出范围(注意
pt_regs
结构已经用ENOSYS
为rax
的值创建)。 - 通过间接跳转调度到系统调用。
- 将系统调用的 return 值 (
rax
) 保存到堆栈上pt_regs
中的rax
。 - 再次检查当前任务是否设置了
_TIF_ALLWORK_MASK
,如果是则跳转到慢return路径. - 恢复调用方上下文并发出
sysret
。
慢 return 路径
- 将之前没有保存的寄存器保存在
pt_regs
中(rbx
,rbp
,r12
-r15
). - 调用
syscall_return_slowpath
,定义here.
请注意,第 2 点最终会调用 trace_sys_exit
。
慢路径
- 将之前没有保存的寄存器保存在
pt_regs
中(见上文) - 调用
do_syscall_64
,定义here。
点 2 将调用 syscall_trace_enter
。
所以慢速与快速路径与 ptrace
有关。我没有深入研究代码,但我想如果调用者不需要 ptrace
,则整个机器都会被跳过。
这确实是一个重要的优化。