zoukankan      html  css  js  c++  java
  • 《Linux内核分析》课程第四周学习总结

    姓名:何伟钦

    学号:20135223

    ( *原创作品转载请注明出处*)

    ( 学习课程:《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

     

     

     

    学习内容:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    一、用户态、内核态和中断

    与系统调用打交道的方式:通过库函数,把系统调用给封装起来

    1、用户态vs内核态:

          (1)一般现代CPU都有几种不同的指令执行级别:在高级别的状态下,代码可以执行特权指令,访问任意的物理地址,这种CPU执行级别对应着内核态;

          在相应的低级别执行状态下,代码的掌控范围会受到限制,只能在对应级别允许的范围内活动

          (2)为什么有权限级别的划分:为了防止系统崩溃以及恶意代码的入侵,通过划分权限级别来让系统更稳定

          举例:Intel x86 CPU有四种不同的执行级别0-3,Linux只使用了其中的0级和3级分别来表示内核态和用户态

          区分:在Linux中,地址空间是一个显著的标志:

                                     0xc0000000以上的地址空间只能在内核态下访问

                                    0x00000000-0xbfffffff的地址空间在两种状态下都可以访问

          注意:地址空间指的是逻辑地址而不是物理地址

    2、中断

        (1)中断处理是从用户态进入内核态主要的方式,系统调用只是一种特殊的中断

        (2)当用户态切换到内核态时,必须保存用户态的寄存器上下文

        (3)中断/int指令会在堆栈上保存一些寄存器的值,如:

                ①用户态栈顶地址;  ②当时的状态字;    ③当时的cs:eip的值

        (4)中断发生后第一件事:保存现场(进入中断程序,保存需要用到的寄存器的数据)

                                                      SAVE_ALL:把其他的寄存器的值给push到内核堆栈里边去

                中断处理结束前最后一件事:恢复现场(退出中断程序,恢复保存寄存器的数据)

                                          RESTOTRE_ALL:把用户态保存的寄存器再popl出来

        (5)Iret指令与中断信号(包括int指令)发生时的CPU做的动作相反

    二、系统调用

         (一) 系统调用的意义

          

          (二)API和系统调用:API与系统调用不是一一对应的

          

          

         (三)应用程序,封装程序,系统调用处理程序及系统调用服务例程之间的关系

          

         (四)系统调用的三层皮:

               ①xyz(API)

               ②system_call(中断向量对应的中断服务程序),

               ③sys_xyz (中断服务程序)

      1. 当用户态进程调用一个系统调用时,CPU切换到内核态并开始执行一个内核函数。

      2. Linux中是通过执行int $0x80来执行系统调用,这条汇编指令产生向量为128的编程异常 —— 即中断向量0x80与System_call绑定起来。

      3. 系统调用号将函数xyz()和中断服务程序sys_xyz关联起来。

       (五) 参数传递

    1. 内核实现了很多不同的系统调用,进程用系统调用号这个参数指明需要哪个系统调用。

    2. system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,使用eax寄存器传递系统调用号。

    3. 寄存器传递参数的限制:

      ①每个参数的长度不能超过寄存器的长度,即32位
      ②在系统调用号(eax)之外,参数的个数不能超过6个(ebx,ecx,edx,esi,edi,ebp)
      ③超过6个的情况下,使用某一个寄存器作为指针,进入内核态之后可以访问所有的地址空间,通过某一片区域传递参数。

    三、使用库函数API和C代码中嵌入汇编代码触发同一个系统调用

    (一)使用库函数API获取系统当前时间

    代码:

    运行结果:

    (二) 使用嵌入式汇编代码获取系统当前时间

    代码如下:

    运行结果:

    用户态向内核态传递了一个系统调用号和传递了参数 ,系统调用返回值使用eax存储,参数用ebx存储

    (三)进行C语言代码实例编写:

    代码如下:

    运行结果:

    (四)编写嵌入式汇编代码

    代码如下:

    运行结果:

    通过内嵌汇编代码可以清晰的看出调用系统调用的工作过程:

    ①将ebx寄存器清零,表示无参数传入。

    ②将需要调用的系统调用号赋值给eax寄存器

    ③执行int 0x80来执行系统调用。

    ④eax寄存器保存了返回值,将它分别赋值给输出uid或gid变量。

    (在Linux系统中是通过激活0x80中断来触发系统调用的,需要调用的系统调用号实现赋值给eax存储器,如果有传入参数可赋值给ebx寄存器,如果多于1个则按顺序赋值给ebx、ecx、edx、esi、edi、ebp,如果超过6个则通过指针变量指向另一片堆栈区,如果无参数传入则赋值为0)

  • 相关阅读:
    Oracle11g新建用户及用户表空间
    PLSQL连接oracle12c
    Zabbix微信报警脚本及写触发记录
    使用document.select(Jquery Css selector) selector:看jsoup文档来敲案例学习 selector选择器
    仙女打卡day1
    XML的解析(读取),附带源码与运行效果图 (day01)
    [Luogu] P7077 函数调用
    [Luogu] P5815 [CQOI2010]扑克牌
    [Luogu] CF364D Ghd
    [Luogu] P4823 [TJOI2013]拯救小矮人
  • 原文地址:https://www.cnblogs.com/20135223heweiqin/p/5297608.html
Copyright © 2011-2022 走看看