zoukankan      html  css  js  c++  java
  • 201920201 20199320《Linux内核原理与分析》第五周作业

    第四章 系统调用的三层机制(上)

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

    1. Intel x86 CPU有4种不同的执行级别,分别是0、1、2、3,数字越小,特权越高,而Linux只采用了0,3两个特权级别,分别对应内核态和用户态。
    2. 内核态和用户态的区别:内核态时,CS:EIP的值可以是任意地址,用户态时只能访问0x00000000~0xbfffffff的地址空间。
    3. 进入内核态的两种方式:
      (1)可能是硬件中断
      (2)可能是用户态执行程序时调用了一个系统调用,陷入了内核态,叫做Trap.
    4. 用户切换到内核态时,会保存用户态寄存器上下文(包括用户态栈顶指针、当时的状态字、当时的CS:EIP的值),同时,要把内核态的寄存器的值放到当前CPU中。

    二、系统调用

    1. 含义:操作系统为用户态进程与硬件设备进行交互提供的一组接口。
    2. 功能(特性):把用户从底层的硬件编程中解救出来;极大地提高系统的安全性;使用户程序具有可移植性。
    3. API:应用程序编程接口,内部使用了系统调用的封装例程,主要目的是发布系统调用。
    4. API和系统调用的关系:一个API对应一个或多个系统调用,一个系统调用可能被多个API调用。不涉及与内核交互的API内部不会封装系统调用。

    三、使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    (以sys_rename()给文件重命名的函数为例)

    1. 使用库函数API触发一个系统调用

      C语言代码如下:

      执行结果如下图:

    2. 汇编语言触发系统调用

      汇编代码如下:

      执行结果如下图:

    分析:

    主要汇编代码如下:

    asm volatile("movl %2,%%ecx\n\t" //newname存入ecx 
    
          "movl %1,%%ebx\n\t" //oldname存入ebx 
    
          "movl $0x26,%%eax\n\t" //系统调用号存入eax 
    
          "int $0x80" //触发系统调用,陷入内核态
    
          :"=a"(ret) 
    
          :"b"(oldname),"c"(newname) );
    

    这里,把系统调用号38(16进制是0x26)存入 eax,将 oldname 存入 ebx,将 newname 存入 ecx,通过执行 int $0x80 来执行系统调用,使应用程序陷入内核态,system_call 根据传入的系统调用号在系统调用列表中查找对应的内核函数,根据 ebx 和 ecx 中保存的参数调用内核函数 sys_rename,执行完后将执行结果存放到 eax 中,最后返回 eax 中的值。

    四、总结:

    本章主要学习了系统调用的3层机制的系统调用工作机制:当用户态进程调用一个系统调用时,CPU切换到内核态并开始执行system_call和系统调用内核函数。具体来说,通过执行int $0x80来触发系统调用,进入内核后,开始执行中断向量为128对应的中断服务程序system_call,这时,通过系统调用号将API函数和系统调用内核函数关联起来,这里需要EAX寄存器传递系统调用号。

  • 相关阅读:
    悼念丹尼斯·里奇,那个给乔布斯提供肩膀的巨人(转载)
    c# 做成Windows服务
    Visual Studio 2010 新建完项目编译就出错
    C#调用Win32 的API函数User32.dll
    c# Remoting小例子
    backgroundworker使用 实现进度条ProgressBar
    winform最小化后隐藏到右下角,单击或双击后恢复
    关于Thread的实例
    c# 捕获的异常写到日志里
    C# delegate and event 规范写法
  • 原文地址:https://www.cnblogs.com/liangxu111/p/11701615.html
Copyright © 2011-2022 走看看