69

我研究了 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 会发生什么?

4

4 回答 4

92
  • syscall是进入内核模式的默认方式x86-64此指令在 Intel 处理器的 32 位操作模式下不可用。
  • sysenter是最常用于在 32 位操作模式中调用系统调用的指令。它类似于syscall,虽然使用起来有点困难,但这是内核关心的问题。
  • int 0x80是调用系统调用的传统方式,应避免使用。

调用系统调用的首选方法是使用vDSO,它是映射在每个进程地址空间中的内存的一部分,允许更有效地使用系统调用(例如,在某些情况下根本不进入内核模式)。int 0x80与传统方式相比,vDSO 还处理更困难的处理syscallsysenter指令。

另外,请参阅thisthis

于 2012-10-09T19:18:54.770 回答
23

在这里的回答涵盖了你的问题。

在实践中,最近的内核正在实现VDSO,特别是为了动态优化系统调用(内核将 VDSO 设置为一些最适合当前处理器的代码)。所以你应该使用VDSO,对于现有的系统调用,你最好使用libc提供的接口。

请注意,AFAIK,简单系统调用成本的很大一部分是从用户空间到内核并返回。因此,对于某些系统调用(可能gettimeofdaygetpid...),VDSO 甚至可以避免这种情况(并且在技术上可能会避免进行真正的系统调用)。对于大多数系统调用(如open, read, send, mmap....),系统调用的内核成本大到足以使用户空间到内核空间转换(例如使用SYSENTERSYSCALL机器指令而不是INT)的任何改进都微不足道。

于 2012-10-09T19:13:48.903 回答
7

在更改之前要注意这一点:在执行 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用于系统调用

于 2013-10-08T19:48:54.687 回答
-5

int 0x80是一个更好的术语,表示它是对内核的系统调用,告诉它做某事。

含义和解释可以互换,“进行系统调用”或“发布 int 80h”。

这与 DOS 时代没有什么不同:

  • 调用 int 21h 让 DOS 做一些依赖于 AX 寄存器和可选的 ES:DX 寄存器对的事情,
  • int 13h 是 BIOS 硬盘处理程序。
  • int 10h 是 EGA/VGA 屏幕。
  • int 09h 是键盘处理程序。

这里的共同主题是,当调用中断/系统调用时,内核会检查寄存器的状态以查看需要什么类型的系统调用。通过查看例如,例如eax注册并确定要执行的操作,内部上下文切换到内核空间,执行过程并将上下文切换回用户空间,并可以选择返回调用结果,即它是成功的还是失败的。

于 2012-10-09T19:11:03.630 回答