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

    第一部分 笔记

    内核态:高执行级别,代码可以执行特权指令,访问任意的物理内存,CPU的执行级别对应的就是内核态。
    用户态:与内核态相对应的低级别指令,代码能够掌控的范围会受到限制。
    
    Intel x86 CPU有四种不同的执行级别,分别是0,1,2,3其中数字越小,特权越高。Linux操作系统只采用了其中的0和3两个特权级别,分别对 应内核态和用户态.用户态和内核态很显著的区别方法就是CS:EIP的指向范围,内核态CS:EIP的值是任意的,即可以访问所有的地址空间。 用户态只能访问其中的一部分内存地址(0x00000000-0xbbbbbbbf),0xc0000000以上的地址只能在内核态下访问。
    CS:代码段选择寄存器  EIP:偏移量寄存器。
    

    中断:由中断触发进入内核态。硬件中断或是由调用系统调用(Trap)引起中断,陷入内核态。从用户态切换到内核态,将用户态寄存器的上下文保存起来,同时将内核态寄存器的值放入当前CPU中。
    系统调用的特点:把用户从底层的硬件编程中解放出来;极大的提高了系统的安全性;使用户程序具有可移植性。
    
    系统调用的库函数就是我们使用的操作系统提供的API,系统调用是通过软中断向内核发出中断请求,int指令的执行中触发断请求。
    libc函数库内部定义的一些API内部就使用了系统调用的封装历程。每个系统调用对应一个系统调用的封装例程。
    

    • User Mode表示用户态,Kernel Mode表示内核态。xyz()为API函数,触发int $0x80()的中断,对应system_call内核代码的起点,即中断向量0x80对应的中断服务程序入口,内部会有sys_xyz()系统调用处理函数,再ret_from_sys_call。
    • 系统调用的3层机制:xyz();system_call;sys_xyz()。
    • 系统调用号:内核通过给每个系统调用一个编号来区分。将API函数xyz()和系统调用内核函数sys_xyz()关联起来。
    • 用户进程必须指明需要哪一个系统调用,使用EAX寄存器传递一个名为系统调用号的参数。
    • 统调用从用户态切换到内核态时使用的不同的堆栈,所以参数的传递无法通过参数压栈的方式进行传递。参数按照顺序赋值给EBX ECX EDX ESI EDI EBP 参数的个数不能超过6个寄存器。如果参数过多,就把寄存器作为指针指向内存,以传递更多的参数。

    第二部分 实验

    • 使用库函数API系统调用
    #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_mda,t->tm_hour,t->tm_min,t->tm_sec);
     return 0;
    }
    
    

    • 使用C代码中嵌入汇编代码系统调用
    #include<stdio.h>
    #include<time.h>
    int main()
    {
     time_t tt;
     struct tm *t;
     asm volatile
     (
        "mov $0,%%ebx
    	"//把EBX寄存器清0
    	"mov $0xd,%%eax
    	"//eax用于传递系统调用号
    	"int $0x80
    	"//触发系统调用陷入内核执行13好系统调用的内核处理函数
    	"mov %%eax,%0
    	"//系统调用的返回值通过eax返回
    	:"=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;
     }
    	
    

    • 使用两种方法实现触发系统调用-38


    • 通用的触发系统调用函数syscall

    #include<stdio.h>
    #include<sys/syscall.h>
    int main()
    {
     int ret;
     char oldname[]="hello.c";
     char newname[]="newhello.c";
     ret=syscall(38,oldname,newname);
     if (ret==0)
        printf("Renamed successfully
    ");
    else
        printf("Unable to renam the file
    ");
     return 0;
     }
    


    libc没有提供某个系统调用的封装,可以利用libc提供的syscall函数直接调用

  • 相关阅读:
    LCD时序中设计到的VSPW/VBPD/VFPD/HSPW/HBPD/HFPD总结【转】
    【读书笔记::深入理解linux内核】内存寻址【转】
    解决阿里云无法正常使用samba的问题【转】
    谈谈Linux内核驱动的coding style【转】
    linux下使用indent整理代码(代码格式化)【转】
    gcc编译选项【转】
    DirectFB简介以及移植[一]【转】
    Android Framebuffer介绍及使用【转】
    Windows Live Writer离线博客工具使用教程(适用于博客园、CSDN、51CTO等等博客)【转】
    jenkins 入门教程(上)【转】
  • 原文地址:https://www.cnblogs.com/20199321zjy/p/11686847.html
Copyright © 2011-2022 走看看