zoukankan      html  css  js  c++  java
  • 2020-2021-1 20209323《Linux内核原理与分析》第五周作业

    一、系统调用的三层机制

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

    • 用户态:较低的执行级别,只能访问一部分内存,只能执行一部分指令。
    • 内核态:高级执行级别,可以访问任意物理内存,可以执行特权指令。
    • 中    断:系统从用户态进入内核态的主要方式。有硬件中断和软中断两种,系统调用就是通过软中断进入内核态。

    2、系统调用

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

    • 把用户从底层的硬件编程中解放出来
    • 极大的提高了系统的安全性
    • 使用户程序具有可移植性

    3、API和系统调用

    1)应用编程接口(application program interface, API) 和系统调用是不同的

    • API只是一个函数定义,系统调用通过软中断向内核发出一个明确的请求
    • Libc库定义的一些API引用了封装例程,一般每个系统调用对应一个封装例程,库再用这些封装例程定义出给用户的API

    2)不是每个API都对应一个特定的系统调用。

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

    3)返回值

    • 大部分封装例程返回一个整数,其值的含义依赖于相应的系统调用
    • -1在多数情况下表示内核不能满足进程的请求
    • Libc中定义的errno变量包含特定的出错码

    4、应用程序、封装例程、系统调用处理程序及系统调用服务例程之间的关系

    二、实验(使用库函数API和C代码嵌入汇编代码触发同一个系统调用)

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

    //time.c
    #include<stdio.h> #include<time.h> int main()
    { time_t tt;
    struct tm *t; tt = time(NULL); 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; }

    虚拟机使用的是64位系统,gcc编译时需要加一个m32的参数输出32位的机器码, gcc -m32 -o time time.c 

    从运行结果可以看出,当前时间的月份提前了一个月,这是因为:结构体tm中定义的月份是从0开始计数的,所以为了得到当前时间,需要将mon+1,结构体tm如下:

    struct tm
    {    
        int tm_sec;  /*秒,正常范围0-59, 但允许至61*/    
        int tm_min;  /*分钟,0-59*/    
        int tm_hour; /*小时, 0-23*/    
        int tm_mday; /*日,即一个月中的第几天,1-31*/    
        int tm_mon;  /*月, 从一月算起,0-11 1+p->tm_mon;  */ 
        int tm_year;  /*年, 从1900至今已经多少年 1900+ p->tm_year;  */ 
        int tm_wday; /*星期,一周中的第几天, 从星期日算起,0-6*/    
        int tm_yday; /*从今年1月1日到目前的天数,范围0-365*/    
        int tm_isdst; /*日光节约时间的旗标*/
    };

     2、C代码中嵌入汇编代码触发一个系统调用

    用汇编方式触发系统调用获取系统当前时间,time_asm.c源代码如下, 可见,除了"tt = time(NULL);"一句用内嵌汇编代替外,与前述的“使用库函数API触发一个系统调用”中的代码完全一致。

    #include<stdio.h>
    #include<time.h>
    
    int main(){
        time_t tt;
        struct tm *t;
        asm volatile(
            "movl $0,%%ebx;
    	"    //把ebx寄存器清0
            "movl $0xd,%%eax;
    	"  //eax用于传递系统调用号
            "int $0x80;
    	"        //触发系统调用陷入内核执行系统调用内核处理函数
            "movl %%eax,%0;
    	"    //系统调用的返回值通过eax返回
            :"=m"(tt)
            :
            :"eax","ebx"
        );
        t = localtime(&tt);
        printf("time:%d:%d:%d:%d:%d:%d:
    ",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
        return 0;
    }

     
  • 相关阅读:
    Windows 系统光盘刻录教程-光盘怎样刻录?刻录数据光盘用"轨道一次写入"还是"光盘一次写入"?
    日本比中国快一个小时,泰国比中国慢一个小时
    轻量级微服务全局架构图-来自于黄勇老师
    2018-2-13-win10-uwp-读写csv-
    2018-8-28-win10-uwp-MVVM入门
    2018-12-25-win10-uwp-显示SVG
    2018-8-27-C#-powshell-调用
    2019-9-2-visual-studio-2015-warning-MSB3246
    2018-10-2-win10-uwp-win2d-特效
    2019-9-2-生成密码
  • 原文地址:https://www.cnblogs.com/qingyu-sun/p/13942525.html
Copyright © 2011-2022 走看看