我研究了 Linux 内核,发现对于 x86_64 架构,中断int 0x80
不适用于调用系统调用1。
对于 i386 架构(32 位 x86 用户空间),更可取的是:syscall
或者int 0x80
为什么?
我使用 Linux 内核版本 3.4。
脚注 1:int 0x80
在某些情况下可以在 64 位代码中使用,但从不推荐。 如果在 64 位代码中使用 32 位 int 0x80 Linux ABI 会发生什么?
我研究了 Linux 内核,发现对于 x86_64 架构,中断int 0x80
不适用于调用系统调用1。
对于 i386 架构(32 位 x86 用户空间),更可取的是:syscall
或者int 0x80
为什么?
我使用 Linux 内核版本 3.4。
脚注 1:int 0x80
在某些情况下可以在 64 位代码中使用,但从不推荐。 如果在 64 位代码中使用 32 位 int 0x80 Linux ABI 会发生什么?
syscall
是进入内核模式的默认方式x86-64
。此指令在 Intel 处理器的 32 位操作模式下不可用。sysenter
是最常用于在 32 位操作模式中调用系统调用的指令。它类似于syscall
,虽然使用起来有点困难,但这是内核关心的问题。int 0x80
是调用系统调用的传统方式,应避免使用。调用系统调用的首选方法是使用vDSO,它是映射在每个进程地址空间中的内存的一部分,允许更有效地使用系统调用(例如,在某些情况下根本不进入内核模式)。int 0x80
与传统方式相比,vDSO 还处理更困难的处理syscall
或sysenter
指令。
我在这里的回答涵盖了你的问题。
在实践中,最近的内核正在实现VDSO,特别是为了动态优化系统调用(内核将 VDSO 设置为一些最适合当前处理器的代码)。所以你应该使用VDSO,对于现有的系统调用,你最好使用libc提供的接口。
请注意,AFAIK,简单系统调用成本的很大一部分是从用户空间到内核并返回。因此,对于某些系统调用(可能gettimeofday
,getpid
...),VDSO 甚至可以避免这种情况(并且在技术上可能会避免进行真正的系统调用)。对于大多数系统调用(如open
, read
, send
, mmap
....),系统调用的内核成本大到足以使用户空间到内核空间转换(例如使用SYSENTER
或SYSCALL
机器指令而不是INT
)的任何改进都微不足道。
在更改之前要注意这一点:在执行 0x80 或 syscall 时,系统调用号会有所不同,例如 sys_write 在 0x80 时为 4,在 syscall 时为 1。
http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html 32 位或 0x80 http://blog.rchapman.org/post/36801038863/linux-system-call-table- for-x86-64用于系统调用
int 0x80
是一个更好的术语,表示它是对内核的系统调用,告诉它做某事。
含义和解释可以互换,“进行系统调用”或“发布 int 80h”。
这与 DOS 时代没有什么不同:
这里的共同主题是,当调用中断/系统调用时,内核会检查寄存器的状态以查看需要什么类型的系统调用。通过查看例如,例如eax
注册并确定要执行的操作,内部上下文切换到内核空间,执行过程并将上下文切换回用户空间,并可以选择返回调用结果,即它是成功的还是失败的。