首页 > 解决方案 > `entry_SYSCALL64_slow_path` 和 `entry_SYSCALL64_fast_path` 的区别

问题描述

我们知道系统调用会调用entry_64.Sentry_SYSCALL_64中的函数。当我阅读源代码时,我发现在准备寄存器后有两种不同类型的调用,一种是,另一种是。你能说出这两个函数的区别吗?entry_SYSCALL64_slow_pathentry_SYSCALL64_fast_path

标签: linuxlinux-kernelsystem-calls

解决方案


进入entry_SYSCALL_64Linux 后将:

  1. 交换gs以获取每个 cpu 的参数。
  2. 从上面的参数设置堆栈。
  3. 禁用 IRQ。
  4. 在堆栈上创建部分结构。 pt_regs这会保存调用者上下文。
  5. 如果当前任务有_TIF_WORK_SYSCALL_ENTRY或已_TIF_ALLWORK_MASK设置,则进入慢速路径
  6. 否则输入快速路径。

_TIF_WORK_SYSCALL_ENTRY在此处定义,并带有注释说明:

/*
 * work to do in syscall_trace_enter().  Also includes TIF_NOHZ for
 * enter_from_user_mode()
 */

_TIF_ALLWORK_MASK似乎没有为 x86 定义,这里有 MIPS 的定义,并带有注释说明:

/* work to do on any return to u-space */

快速路径

Linux 将:

  1. 启用 IRQ。
  2. 检查系统调用号是否超出范围(请注意,该pt_regs结构已使用ENOSYS的值创建rax)。
  3. 通过间接跳转调度到系统调用。
  4. rax将系统调用的返回值 ( ) 保存raxpt_regs堆栈中。
  5. 再次检查_TIF_ALLWORK_MASK当前任务是否设置了,如果是则跳转到慢速返回路径
  6. 恢复调用者上下文并发出sysret.

慢回程

  1. 将之前未保存的寄存器保存在pt_regs( rbx, rbp, r12- r15) 中。
  2. 调用syscall_return_slowpath,定义在这里

请注意,第 2 点最终会调用trace_sys_exit.

慢路

  1. 将之前未保存的寄存器保存在pt_regs(见上文)
  2. 调用do_syscall_64,定义在这里

第 2 点将调用syscall_trace_enter.


因此,慢速与快速路径与ptrace. 我还没有深入研究代码,但我想如果ptrace调用者不需要,整个机器都会被跳过。
这确实是一个重要的优化。


推荐阅读