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:\n",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;\n\t"    //把ebx寄存器清0
        "movl $0xd,%%eax;\n\t"  //eax用于传递系统调用号
        "int $0x80;\n\t"        //触发系统调用陷入内核执行系统调用内核处理函数
        "movl %%eax,%0;\n\t"    //系统调用的返回值通过eax返回
        :"=m"(tt)
        :
        :"eax","ebx"
    );
    t = localtime(&tt);
    printf("time:%d:%d:%d:%d:%d:%d:\n",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
    return 0;
}

 

 

 

 
posted @ 2020-11-08 16:56  qingyu_sun  阅读(166)  评论(1编辑  收藏  举报