系统调用如何在Linux上实际发生?

受这个问题的启发

我该如何强制GDB进行反汇编?

并与此相关

什么是INT 21h?

在linux下如何实际发生系统调用? 调用执行时会发生什么情况,直到调用实际的内核例程?

Solutions Collecting From Web of "系统调用如何在Linux上实际发生?"

假设我们正在谈论x86:

  1. 系统调用的ID存入EAX寄存器
  2. 系统调用所需的任何参数都存入系统调用所指定的位置 。 例如,一些系统调用期望它们的参数驻留在EBX寄存器中。 其他人可能会认为他们的论点是坐在最上面的。
  3. 一个INT 0x80中断被调用。
  4. Linux内核为EAX寄存器中的ID标识的系统调用提供服务,将任何结果存放在预定的位置。
  5. 调用代码使用任何结果。

我可能有点生疏,已经有几年了…

给出的答案是正确的,但我想补充说,有更多的机制进入内核模式。 每个最近的内核都在每个进程的地址空间中映射“vsyscall”页面。 它只包含最有效的系统调用陷阱方法。

例如,在常规的32位系统上,它可能包含:

 0xffffe000: int $0x80 0xffffe002: ret 

但是在我的64位系统上,我可以使用syscall / sysenter指令来访问更高效的方法

 0xffffe000: push %ecx 0xffffe001: push %edx 0xffffe002: push %ebp 0xffffe003: mov %esp,%ebp 0xffffe005: sysenter 0xffffe007: nop 0xffffe008: nop 0xffffe009: nop 0xffffe00a: nop 0xffffe00b: nop 0xffffe00c: nop 0xffffe00d: nop 0xffffe00e: jmp 0xffffe003 0xffffe010: pop %ebp 0xffffe011: pop %edx 0xffffe012: pop %ecx 0xffffe013: ret 

这个vsyscall页面还映射了一些可以在没有上下文切换的情况下完成的系统调用。 我知道某些gettimeofdaytimegetcpu被映射到那里,但是我想getpid也适合在那里。

这已经在回答
Linux中的系统调用如何实现?
可能与这个问题不匹配,因为“系统调用”的用法不同。

基本上,它非常简单:内存中的某个地方有一个表,其中存储了每个系统调用号码和相应处理程序的地址(请参阅http://lxr.linux.no/linux+v2.6.30/arch/x86/kernel/syscall_table_32 .S为x86版本)

INT 0x80中断处理程序只是将参数从寄存器中取出,放在(内核)堆栈上,然后调用相应的系统调用处理程序。