x86_64 linux 中的系统调用是否仍会产生中断?

arr*_*ags 5 linux interrupts

在旧版本的 linux 架构中,系统调用在执行过程中总是会产生中断。它们将通过将系统调用号设置为 %eax 并将参数设置为 %ebx、%ecx 等,然后发出特定中断 int 0x80 来执行。因此,系统调用可以说是系统上软件中断的常见原因。

然而,在 x86_64 的现代体系结构上,有一个特定的系统调用指令“syscall”,它绕过了使用中断 0x80 的需要,因此根本不需要中断描述符表。虽然我相信之前为 syscall 生成中断的方法仍然受支持,但 syscall 指令似乎是在实践中完成的方式。

因此,我的问题是:说系统调用产生中断是否不再正确?例如,系统调用是否仍会增加在 vmstat 的“中断”列输出中看到的数字?

Joh*_*ald 5

是的,Linux x86_64 的现代 C 代码使用 syscall 指令,例如 glibc sysdeps/unix/sysv/linux/x86_64/syscall.S。不,这并不意味着系统调用中断会因为兼容性而消失。

https://www.kernel.org/doc/Documentation/x86/entry_64.txt

x86 架构有多种不同的方式来跳转到内核代码。大多数这些入口点都在 arch/x86/kernel/traps.c 中注册,并在 arch/x86/entry/entry_64.S(64 位)、 arch/x86/entry/entry_32.S(32 位)和 arch/x86/entry/entry_32.S(32 位)中实现/x86/entry/entry_64_compat.S 实现 32 位兼容性系统调用入口点,从而为 32 位进程提供在 64 位内核上运行时执行系统调用的能力。

IDT 向量分配列在 arch/x86/include/asm/irq_vectors.h 中。

其中一些条目是:

  • system_call:64 位代码的系统调用指令。

  • Entry_INT80_compat:来自 32 位或 64 位代码的 int 0x80;无论哪种方式都兼容系统调用。

  • Entry_INT80_compat、ia32_sysenter:来自 32 位代码的 syscall 和 sysenter

对于只读系统调用(gettimeofday),vDSO 根本不进入内核模式。

可以通过多种方式分析系统调用,例如 ftrace 或 eBPF。除了在 64 位模式下已过时之外,中断还会因系统调用以外的原因而发生。