zoukankan      html  css  js  c++  java
  • 20135202闫佳歆--week4 系统调用(上)--学习笔记

    此为个人笔记存档

    week 4 系统调用(上)

    一、用户态、内核态和中断处理过程

    用户通过库函数与系统调用联系起来。

    1.内核态

    在高执行级别下,代码可以执行特权指令,访问任意的物理地址

    2.用户态:

    代码的掌控范围受到限制。

    intel x86 CPU有四个权限分级,0-3。Linux只取两种,0是内核态,3是用户态
    区分权限级别使得系统更加稳定。

    如何区分用户态与内核态?
    cs:eip。[代码段选择寄存器:偏移量寄存器]
    通过cs寄存器的最低两位,表示当前代码的特权级:
    【针对逻辑地址】
    0xc0000000以上的空间只能在内核态下访问
    0x00000000-0xbfffffff两种状态下都可以访问

    如何进行切换?
    中断。

    3.中断

    中断处理是从用户态进入内核态的主要方式。

     - 硬件中断 
     - 系统调用
    
    1. 寄存器上下文
      从用户态切换到内核态时,必须保存用户态的寄存器上下文到内核堆栈中,同时会把当前内核态的一些信息加载,例如cs:eip指向中断处理程序入口。
      • 用户态栈顶地址
      • 当时状态字
      • 当时cs:eip
      • ……
    2. 中断发生后的第一件事就是保存现场 - SAVE_ALL
      中断处理结束前最后一件事是恢复现场 - RESTORE_ALL

    二、系统调用概述

    1. 系统调用的意义:

    操作系统为用户态进程与硬件设备进行交互提供了一组接口,就是系统调用。

    - 远离底层硬件编程
    - 安全性
    - 可移植性
    

    2. API - 应用编程接口

    与系统调用区别:

    - API只是一个函数定义
    - 系统调用是通过软中断向内核发出一个明确的请求。
    

    一般每个系统调用对应一个封装例程,库再用这些封装例程定义出用户的API,方便用户使用。
    也就是说,API与系统调用不是一一对应的

    API可以:
    - 直接提供用户态服务
    - 一个单独的API可能调用几个系统调用
    - 不同的API可能调用了同一个系统调用
    

    返回值:

     - 大部分封装例程返回一个整数
     - -1表示失败,不能满足请求 
     - errno 特定出错码
    

    3.所谓“扒开系统调用的三层皮”

    • API(xyz)
    • 中断向量(system_call)
    • 中断服务程序(sys_xyz)
      enter description here
      1.系统调用的服务例程中,中断向量0x80与system_call绑定起来。(Linux中可以通过执行int $128来执行系统调用。)
      2.system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,即系统调用号。
      3.系统调用号将xyz与sys_xyz关联起来。调用号在eax中。

    系统调用的参数传递:

    • 函数调用——压栈
    • 用户态到内核态——寄存器传递。
      每个参数长度不能超过32位,个数不能超过6个。
      超过的话?
      使某个寄存器中存储指针,指向内存,内存中存储参数。

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

    1.使用库函数API获取系统当前时间

    使用time(),代码如下:

    #include<stdio.h>
    #include<time.h>
    
    int  main() 
    {
        time_t tt;  
        struct tm *t;//构造一个结构体,方便读取
        tt = time(NULL);//time系统调用
        t = localtime(&tt);  
        printf("time:%d:%d:%d:%d:%d:%d
    ", t->tm_year+1900, t->tm_mon, t->tm_mday,  t->tm_hour, t->tm_min, t->tm_sec);
        return 0; 
    } 
    

    执行如下:
    enter description here

    2.使用C代码中嵌入汇编代码触发系统调用获取系统当前时间

    代码如下:

    #include<stdio.h>
    #include<time.h>
    
    int  main() 
    {
        time_t tt;  
        struct tm *t;
        asm volatile(  
            "mov $0,%%ebx
    	"  # 把ebx清零,相当于传参数
            "mov $0xd,%%eax
    	"    # 把0xd放入eax中,即系统调用号13,指time 
            "int $0x80
    	"  
            "mov %%eax,%0
    	"  # 返回值是在eax中,%0指tt,把返回值放到tt中去。
            : "=m" (tt)   
        );  
        t = localtime(&tt);  
        printf("time:%d:%d:%d:%d:%d:%d
    ", t->tm_year+1900, t->tm_mon, t->tm_mday,  t->tm_hour, t->tm_min, t->tm_sec);
        return 0; 
    } 
    

    可以从中看出用户态向内核态做了什么:
    1.传递了一个系统调用号 - eax
    2.传递了参数 - ebx

    执行如下:
    enter description here

  • 相关阅读:
    Screen Space Soft Shadows
    立体涂鸦的草图渲染
    什么是Civil3D
    Visual Studio 和 .NET Framework
    编程语言的选择
    Civil3D二次开发能做些什么
    Civil3D二次开发Cookbook
    Civil3D跟AutoCAD是什么关系
    C#启示录:尝鲜版
    Thinking In DesignPattern
  • 原文地址:https://www.cnblogs.com/20135202yjx/p/5281209.html
Copyright © 2011-2022 走看看