简体   繁体   English

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

[英]How does a syscall actually happen on linux?

Inspired by this question 灵感来自这个问题

How can I force GDB to disassemble? 如何强制GDB反汇编?

and related to this one 并与此相关

What is INT 21h? 什么是INT 21h?

How does an actually system call happen under linux? 如何在Linux下实际发生系统调用? what happens when the call is performed, until the actual kernel routine is invoked ? 执行调用时会发生什么,直到调用实际的内核例程?

Assuming we're talking about x86: 假设我们在谈论x86:

  1. The ID of the system call is deposited into the EAX register 系统调用ID存入EAX寄存器
  2. Any arguments required by the system call are deposited into the locations dictated by the system call . 系统调用所需的任何参数都存放在系统调用指定位置 For example, some system calls expect their argument to reside in the EBX register. 例如,某些系统调用期望它们的参数驻留在EBX寄存器中。 Others may expect their argument to be sitting on the top of the stack. 其他人可能会期望他们的论点位于筹码的顶端。
  3. An INT 0x80 interrupt is invoked. 调用INT 0x80中断。
  4. The Linux kernel services the system call identified by the ID in the EAX register, depositing any results in pre-determined locations. Linux内核为EAX寄存器中的ID标识的系统调用提供服务,将任何结果存储在预定位置。
  5. The calling code makes use of any results. 调用代码使用任何结果。

I may be a bit rusty at this, it's been a few years... 我可能有点生疏,已经有几年......

The given answers are correct but I would like to add that there are more mechanisms to enter kernel mode. 给出的答案是正确的,但我想补充说,有更多的机制进入内核模式。 Every recent kernel maps the "vsyscall" page in every process' address space. 每个最近的内核都映射每个进程的地址空间中的“vsyscall”页面。 It contains little more than the most efficient syscall trap method. 它只包含最有效的系统调用陷阱方法。

For example on a regular 32 bit system it could contain: 例如,在常规32位系统上,它可以包含:

 
0xffffe000: int $0x80
0xffffe002: ret

But on my 64-bitsystem I have access to the way more efficient method using the syscall/sysenter instructions 但是在我的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    

This vsyscall page also maps some systemcalls that can be done without a context switch. 此vsyscall页面还映射了一些可以在没有上下文切换的情况下完成的系统调用。 I know certain gettimeofday , time and getcpu are mapped there, but I imagine getpid could fit in there just as well. 我知道某些gettimeofdaytimegetcpu被映射到那里,但我想getpid也适合那里。

This is already answered at 这已经回答了
How is the system call in Linux implemented? 如何在Linux中实现系统调用?
Probably did not match with this question because of the differing "syscall" term usage. 可能与这个问题不匹配,因为不同的“系统调用”术语用法。

Basically, its very simple: Somewhere in memory lies a table where each syscall number and the address of the corresponding handler is stored (see http://lxr.linux.no/linux+v2.6.30/arch/x86/kernel/syscall_table_32.S for the x86 version) 基本上,它非常简单:内存中的某个位置是一个表,其中存储了每个系统调用号和相应处理程序的地址(请参阅http://lxr.linux.no/linux+v2.6.30/arch/x86/kernel/syscall_table_32 .S for x86版本)

The INT 0x80 interrupt handler then just takes the arguments out of the registers, puts them on the (kernel) stack, and calls the appropriate syscall handler. 然后INT 0x80中断处理程序将参数从寄存器中取出,将它们放在(内核)堆栈上,并调用相应的系统调用处理程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM