如何在Linux中实现系统调用?

时间:2009-01-31 17:17:10

标签: linux operating-system

当我在用户模式下调用系统调用时,如何在OS中处理调用?

是否会调用某些可执行的二进制文件或某些标准库?

如果是,完成通话需要什么样的东西?

6 个答案:

答案 0 :(得分:35)

查看this

  

从2.5版开始,linux   内核引入了一个新的系统调用   Pentium II +的进入机制   处理器。由于性能问题   在现有的Pentium IV处理器上   软件中断方法,   替代系统呼叫条目   机制是用。实现的   SYSENTER / SYSEXIT说明   可在奔腾II +处理器上使用。   本文探讨了这一新内容   机制。讨论仅限于   x86架构和所有源代码   列表基于linux内核   2.6.15.6。

  1. 什么是系统调用?
      

    系统调用提供userland   处理请求服务的方式   来自内核。什么样的   服务?管理的服务   通过操作系统,如存储,   记忆,网络,过程管理   例如,如果用户进程   想要读取文件,它将不得不   进行'打开'和'读'系统调用。   通常不调用系统调用   由进程直接。 C库   提供所有系统的接口   调用

  2. 系统调用会发生什么?
      

    运行内核代码段   用户进程的请求。这段代码   在0环中运行(具有当前权限   等级-CPL-0),这是最高的   x86中的权限级别   建筑。所有用户进程都在运行   在第3环(CPL 3)。

         

    因此,要实现系统调用机制,我们需要的是

         

    1)从环3调用ring 0代码的方法。

         

    2)一些内核代码来处理请求。

  3. 做旧的好方法
      直到一段时间回来,linux习惯了   在所有x86上实现系统调用   使用软件中断的平台。   要执行系统调用,请执行用户进程   将复制所需的系统呼叫号码   到%eax并将执行'int 0x80'。   这将产生中断0x80和   中断服务程序将是   调用。对于中断0x80,这个   例程是“所有系统调用   处理“例行程序。这个程序会   在环0中执行。此例程为   在文件中定义   /usr/src/linux/arch/i386/kernel/entry.S,   将保存当前状态并调用   适当的系统调用处理程序   关于%eax中的值。

  4. 新的闪亮方式
      

    有人发现这个软件   中断方法慢得多   奔腾IV处理器。要解决这个问题   问题,Linus实施了一个   替代系统呼叫机制   利用SYSENTER / SYSEXIT   所有奔腾提供的说明   II +处理器。在走得更远之前   用这种新的做法,让我们来吧   让自己更熟悉   这些说明。

答案 1 :(得分:11)

这取决于系统调用的含义。你的意思是C库调用(通过glibc)还是实际的系统调用? C库调用最终总是使用系统调用。

进行系统调用的旧方法是通过软件中断,即int指令。 Windows有int 0x2e,而Linux有int 0x80。 OS在中断描述符表(IDT)中为0x2e或0x80设置中断处理程序。然后,此处理程序执行系统调用。它将参数从用户模式复制到内核模式(这由特定于操作系统的约定控制)。在Linux上,使用ebxecxedxesiedi传递参数。在Windows上,参数从堆栈中复制。然后处理程序执行某种查找(以查找函数的地址)并执行系统调用。系统调用完成后,iret指令返回用户模式。

新方法是sysentersysexit。这两条指令基本上可以为您完成所有注册工作。操作系统通过模型特定寄存器(MSR)设置指令。之后,它与使用int几乎相同。

答案 2 :(得分:4)

它通过glibc,它在用参数填充寄存器后发出0x80中断。然后内核的中断处理程序在syscall表中查找系统调用并调用相关的sys _ *()函数。

答案 3 :(得分:2)

大大简化了,但是当您尝试访问保留的内存地址时会发生中断。中断将上下文切换到内核模式,并代表用户执行内核代码(实际系统调用)。呼叫完成后,控制权将返回给用户代码。

答案 4 :(得分:2)

程序集中的int X转换为系统调用号n Ex read系统调用可以给出一个数字4 在系统启动时,OS构建一个名为中断描述符表(IDT)的指针表,该表具有系统调用的地址列表以及执行它们所需的权限。
当前特权级别(CPL)保存在CS寄存器的一个位中(技术上是x86上的2位)。
这是int指令所遵循的步骤:
•从IDT中获取第n个描述符,其中n是int的参数 •检查%cs中的CPL是否为< = DPL,其中DPL是描述符中的权限级别。
•如果没有,则用户没有足够的权限执行此操作,并将导致执行int 13指令(一般保护错误),(用户没有足够的权限)
•如果是,则用户代码具有足够的权限进行此系统调用,保存当前执行上下文(寄存器等),因为我们现在切换到内核模式。 这些信息包括寄存器,标志,因为当系统调用被finsihed时,我们希望从我们离开的地方继续执行。 •系统调用的参数保存在内核堆栈中,因为系统调用是在内核模式下执行的。

VSYSCALL(快速系统调用)
每次用户执行系统调用时,Os都会保存机器的当前状态(即寄存器,堆栈指针等)并切换到内核模式以便执行。对于某些系统调用,不必保存所有寄存器。 Ex gettimetime系统调用读取当前时间并且系统调用返回。因此,一些系统调用是通过所谓的vsyscalls实现的。在进行系统调用时,它在用户空间中执行,而不必切换到内核。所以节省了时间 有关vsyscall http://www.trilithium.com/johan/2005/08/linux-gate/的详细信息,请参见此处 在这里Anyone can understand how gettimeofday works?

答案 5 :(得分:0)

系统调用由特殊陷阱指令,系统调用号和参数组成。

  1. 特殊陷阱指令用于从用户模式切换到 内核模式,具有无限权限。
  2. 系统调用号和参数通过寄存器传递。