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


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

    1. 13号系统调用time

    编写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;
    }
    

    经过编译执行:

    问题:月份比当前月份提前一个月,经查阅ctime中的tm结构体,发现月份从0开始计月。

    修改参数,得到正确输出。

    内嵌汇编形式调用:

    #include<stdio.h>
    #include<time.h>
    
    int main(){
            time_t tt;
            struct tm *t;
            asm volatile(
                    "mov $0,%%ebx;
    	"
                    "mov $0xd,%%eax;
    	"
                    "int $0x80;
    	"
                    "mov %%eax,%0;
    	"
                    :"=m"(tt)
            );
            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;
    }
    

    出现段错误

    经参考李明帅同学的博客在汇编代码后添加,代表“eax”“ebx”两个寄存器会被改变,最后执行顺利!

    		:
    		:"eax","ebx"
    

    2. 8号系统调用creat

    函数原型,参数中file为文件名,__mode表示权限。

    #include<fcntl.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    int creat (const char *__file, mode_t __mode)
    

    编写creat.c

    #include<fcntl.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<stdio.h>
    int main(){
            char *pachname="20209326";
            int mode =0777;
            int fd=creat(pachname,mode);
            if(fd==0)
                    printf("create failed!
    ");
            else
                    printf("create successful!
    ");
    }
    

    经过编译执行:

    内嵌汇编形式调用:

    #include<fcntl.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<stdio.h>
    int main(){
            char *pachname="20209326";
            int mode =0777;
            int fd;
            asm volatile(
                    "movl %2,%%ecx
    	"        //将权限mode值赋值给ecx寄存器
                    "movl %1,%%ebx
    	"        //将文件名pachname值赋值给ebx寄存器
                    "movl $0x8,%%eax
    	"      //creat系统调用号为8
                    "int $0x80"                //启动中断
                    :"=a"(fd)                  //输出成功与否
                    :"b"(pachname),"c"(mode)   //输入文件名和权限
            );
            if(fd==0)
                    printf("create failed!
    ");
            else
                    printf("create successful!
    ");
    }
    

    经过编译执行:

    问题:文件的权限与输入的不一致?
    经查阅博客,此处设定的mode的值并不是文件最终的权限,文件最终的权限是按照mode & ~umask得到的,所以如果想按照mode的值设置文件权限,需要在建立文件之前将umask的值设置为0000。加一句umask(0000),即可。

    二、总结

    1.Intel x86 CPU定义了4种不同的执行级别0、1、2、3,数字越小特权越高。Linux系统采用了其中的0、3两个特权级别,分别对应内核态和用户态。内核态下可以访问所有的地址空间,但是在用户态下只能访问0x00000000-0xbfffffff的地址空间,0xc0000000以上的地址空间只能在内核态下访问。
    2.中断处理是从用户态进入内核态的主要方式。硬件中断或是由调用系统调用(Trap)引起中断,陷入内核态。从用户态切换到内核态,将用户态寄存器的上下文保存起来,同时将内核态寄存器的值放入当前CPU中。
    3.Linux下系统调用通过int 0x80中断完成。int指令触发中断机制会在堆栈上保存一些寄存器的值,会保存用户态栈顶地址、当时的状态字、当时的CS:EIP的值。
    4.libc函数库内部定义的一些API内部就使用了系统调用的封装历程。每个系统调用对应一个系统调用的封装例程。
    5.系统调用的3层机制:xyz();system_call;sys_xyz()。
    6.用户进程必须指明需要哪一个系统调用,使用EAX寄存器传递一个名为系统调用号的参数。系统调用从用户态切换到内核态时使用的不同的堆栈,所以参数的传递无法通过参数压栈的方式进行传递。参数按照顺序赋值给EBX ECX EDX ESI EDI EBP 参数的个数不能超过6个寄存器。如果参数过多,就把寄存器作为指针指向内存,以传递更多的参数。

  • 相关阅读:
    希腊字母写法
    The ASP.NET MVC request processing line
    lambda aggregation
    UVA 10763 Foreign Exchange
    UVA 10624 Super Number
    UVA 10041 Vito's Family
    UVA 10340 All in All
    UVA 10026 Shoemaker's Problem
    HDU 3683 Gomoku
    UVA 11210 Chinese Mahjong
  • 原文地址:https://www.cnblogs.com/gann/p/13925004.html
Copyright © 2011-2022 走看看