zoukankan      html  css  js  c++  java
  • 基于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后再沿原路返回

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

  • 相关阅读:
    Educational Codeforces Round 88 (Rated for Div. 2) D. Yet Another Yet Another Task(枚举/最大连续子序列)
    Educational Codeforces Round 88 (Rated for Div. 2) A. Berland Poker(数学)
    Educational Codeforces Round 88 (Rated for Div. 2) E. Modular Stability(数论)
    Educational Codeforces Round 88 (Rated for Div. 2) C. Mixing Water(数学/二分)
    Codeforces Round #644 (Div. 3)
    Educational Codeforces Round 76 (Rated for Div. 2)
    Educational Codeforces Round 77 (Rated for Div. 2)
    Educational Codeforces Round 87 (Rated for Div. 2)
    AtCoder Beginner Contest 168
    Codeforces Round #643 (Div. 2)
  • 原文地址:https://www.cnblogs.com/xcywt/p/4998963.html
Copyright © 2011-2022 走看看