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个寄存器。如果参数过多,就把寄存器作为指针指向内存,以传递更多的参数。

  • 相关阅读:
    Kafka 高级API 实战
    CDH 5.16.1 离线安装 Spark 2.3
    CDH5.16.1 离线安装 Kafka
    CDH5.16.1新增节点
    mysql搭建主从结构
    Kerberos常见错误
    expect实现脚本的 自动交互
    寒假day27
    寒假day26
    寒假day25
  • 原文地址:https://www.cnblogs.com/gann/p/13925004.html
Copyright © 2011-2022 走看看