• 基于int的Linux的经典系统调用实现


       先说明两个概念:中断和系统调用

    一 系统调用: 是应用程序(运行库也是应用程序的一部分)与操作系统内核之间的接口,它决定了应用程序是如何和内核打交道的。

    1  Linux系统调用:2.6.19版内核提供了319个系统调用。比如 exit fork read open close ……

    2  对Windows来说,操作系统提供给应用程序的接口不是系统调用,而是API。比如:ReadFile。我们暂时把API和系统调用等同起来

    3  Linux中,每个系统调用对应一个系统调用号,内核维护了一个系统调用表,通过这张表可以找到对应的系统调用函数。

     

    二 中断

    1  现代的CPU常常可以在多种截然不同的特权级别下执行指令,所以有两种特权级别,分别为用户模式(User Mode)和内核模式(Kernel Mode)

    2  系统调用运行在内核态,应用程序基本都是运行在用户态。用户态要切换到内核态,操作系统一般是通过中断来完成

    3  Linux使用0x80中断作为系统调用的入口,Windows采用0x2E号中断作为系统调用入口

    4  中断是一个硬件或软件发出的请求,要求CPU暂停当前工作转手去处理更加重要的事。

    5  中断一般有两个属性,中断号和中断处理程序。不同的中断有不同的中断号,也对应不同的中断处理程序。

    6  在内核中有一个数组称为中断向量表,这个数组的第n项包含了指向第n号中断的中断处理程序的指针

     

    三 基于int的Linux的经典系统调用实现(进入正题)

    1  以fork为例 

    void main(void)
    {
        fork();  
    }

    2  大概流程就是这样:用户调用fork  ->  eax=2(保存系统调用号到寄存器中) -> int 0x80 (触发中断,切换到内核态)

                ->  在中断向量表中查找(0x80号) -> 执行0x80对应的中断服务程序(system_call)

                ->  在系统调用表中找到系统调用号为2的那一项(通过之前保存的eax=2) -> 执行系统调用(sys_fork)

     

    3  执行流程图如下

     

    4  用户调用某个系统调用,执行到int $0x80时,会保存现场以便恢复,接着将特权状态切换到内核态,然后CPU便会查找中断向量表中的第0x80号元素。

     

    5  切换堆栈:

    1       在执行中断处理函数之前,CPU首先还要进行栈的切换。

    2       在Linux中,用户态和内核态使用的是不同的栈,两者各自负责各自的函数调用。

    3       调用0x80中断时,程序执行流程从用户态切换到内核态,当前栈也必须相应的从用户栈切换到内核栈。从中断处理程序中返回时,再切换回用户栈

    4       “当前栈”指的是ESP的值所在的栈空间,若ESP的值位于用户栈的范围内,那个当前栈就是用户栈,反之就是内核栈。此外,寄存器SS的值还要指向当前栈所在的页

    5       用户栈 -> 内核栈的实际行为就是:

            保存当前的ESP,SS的值   ->   将ESP SS的值设置为内核栈的相应值

          内核栈 -> 用户栈的实际行为就是:

            恢复原来的ESP SS的值

    6       用户态的ESP 和 SS保存在内核栈中,这一行为由i386的中断指令自动地由硬件完成。

    7       中断发生时,CPU切入内核态,还会接着做下面几件事

            找到当前进程的内核栈(每个进程都有独立的内核栈) ->   在内核栈中一次压入用户态的寄存器SS、ESP、EFLAGS、CS、EIP。

    8       系统从系统调用中返回时,需要用iret指令回到用户态,iret会从内核态中弹出寄存器SS、ESP、EFLAGS、CS、EIP的值,使得栈恢复到用户态的状态

     

    6,中断处理程序:切换栈了以后,程序的流程就切换到了中断向量表中记录0x80号中断处理程序,Linux内部的i386中断服务流程如图

            

    执行完sys_fork后再沿原路返回

    参考: 《程序员的自我修养》

  • 相关阅读:
    读取库中的所有表名
    ADOX学习
    自己寫的AccessDBHelper
    C#中Split用法~
    SQL Server:查看SQL日志文件大小SQL脚本
    MS SQL2005 How to find the top 50 cpu execution time.
    跨浏览器的本地存储解决方案
    這個SQL 語句你真的看明白了嗎?
    一个简单的SQL最优写法讨论(1)
    Gmail的标签容纳的邮件数量有限制。
  • 原文地址:https://www.cnblogs.com/xcywt/p/4998963.html
Copyright © 2020-2023  润新知