• 2017-2018-1 20179209《Linux内核原理与分析》第五周作业


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

    环境说明

    实验环境为 Ubuntu16.10 和 实验楼环境。
    选择39号系统调用实验。39号系统调用为mkdir系统调用。

    实验步骤

    有关mkdir系统调用的具体介绍见 linux api 函数——mkdir

    1.用库函数实现mkdir系统调用

    代码很简单:

    #include <sys/stat.h>
    #include <sys/types.h>
    void main(){
            char *p = "./testdir";        //定义char类型指针,说明要创建的目录名称。“./”指在当前目录,其实可以不写
            mkdir(p,S_IRWXU);       //调用mkdir的api函数,第二个参数为所建目录的权限
    

    代码很糙,由于主要目的是实现mkdir系统调用,所以一些跟判断有关的代码我就省略了,直奔主题。

    编译运行,实验结果如下:

    成功!

    2.用嵌入式汇编的C代码实现mkdir系统调用

    代码如下:

    #include <sys/stat.h>
    #include <sys/types.h>
    
    void main(){
    //      char *p = "./testdir";
            int intr;
            mode_t mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;        //定义mode
            asm volatile(
                    "int $0x80;
    	"                                      //执行80号中断,换成intel下汇编类似于 int 80h;
                    : "=a" (intr)                                            //因为mkdir有一个int类型的返回值,所以必须定义一个int来接收
                    : "a" (39),"b" ("testdir"),"c" (mode)        //eax值为39;ebx值为“testdir”;ecx值为mode;这里的三个寄存器的值都是用来传递参数的,eax传递系统调用号,ebx传递mkdir函数的第一个参数,ecx传递mkdir函数的第二个参数。
                    : "memory"
                    );
    }
    


    编译:

    从上图中大家可以看出,这个程序其实我是调试了很多遍之后才编译成功的,主要问题就是集中在嵌入式汇编asm和volatile标题处的问题,这里“_”个数要求非常严格,而且对程序的编译有很大的影响。起初调试时报错是格式问题,在确定格式正确后我只能把问题归结与开头,在我删除volatile时果然又报了不同的错,但程序还是没有编译通过,所以我上网查阅了资料。发现asm和volatile前后各两个下划线,除此外还可以都不加下划线。
    运行:

    我们可以看到,运行后程序没报错,而且也没有生成我们想要的testdir这个文件夹,很显然失败了。。。起初我怕是因为权限问题,专门用系统权限执行后还是没有成功。不过我并没有放弃,把代码拷到实验楼环境下编译运行:


    成功了!
    相同的代码,编译运行后却得到不同的结果,那只可能跟实验环境有关了。
    对比两个实验环境:

    猜测可能是我的Ubuntu版本有些旧吧。知道原因的人也可以留言交流。

    结果分析

    对于上述实验结果的分析,我觉得一张图足以说明它们之间的调用过程与关系。

    这种汇编相当简单,直接把所需要的参数写进输入参数,不用mov指令赋值,所以汇编代码看起来非常简单。一般来说,需要传入的参数不会多于6个,因为通用寄存器共6个,一旦参数个数超过6个就需要申请一块内存地址专门存放参数。

    二.中断

    定义:

    中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。

    分类:

    • 硬中断
    • 可屏蔽中断:这类中断可以通过中断屏蔽寄存器中设定位掩码来关闭。
    • 不可屏蔽中断:无法通过中断处理程序来关闭或推迟的中断,如时钟中断。
    • 软中断

    它是一条CPU指令,用以自陷一个中断。由于软中断指令通常要运行一个切换CPU至内核态的子例程,它常被用作实现系统调用。

    中断与异常:

    中断与异常有所区别,异常在产生时必须考虑与处理时钟同步,因为异常只能在一条指令执行结束后发生,不可能执行一半发生异常,由于与时钟同步,所以异常被称为同步中断。而中断却不是,它可以在任何时候发生。

    异常往往是操作系统不期望发生的事情;相反,操作系统因为有中断的存在,执行效率和正确性方面都有很大的提升。

    上半部与下半部:

    刚看到这个概念时很陌生,最起码在中断这一块,这样的叫法是第一次看到。
    中断服务程序一般都是在中断请求关闭的条件下执行的,以避免嵌套而使中断控制复杂化。但是,中断是一个随机事件,它随时会到来,如果关中断的时间太长,CPU就不能及时响应其他的中断请求,从而造成中断的丢失。因此,Linux内核的目标就是尽可能快的处理完中断请求,尽其所能把更多的处理向后推迟。
    从上半部与下半部产生的原因我们可以总结如下:

    • 上半部必须以最短的时间来执行,因为执行上半部时是关中断状态,无法响应其他中断;
    • 下半部运行时处于开中断状态,所以一些耗时的任务需要放在下半部执行。

    下半部机制:

    所有用于实现将工作推后执行的内核机制都被称作“下半部机制”。目前流行的有如下三种:

    总结

    系统调用是为了让用户程序安全地访问底层资源,它是用户空间访问内核的唯一手段;
    系统调用由操作系统内核提供,运行于内核态。
    Linux的系统调用通过int 0x80实现,用系统调用号来区分入口函数。
    系统调用中的中断,一般是指软中断。
    如果进程上下文和一个下半部共享数据,在访问这些数据之前,需要进制下半部的处理并取得锁的使用权。这里的锁指对共享数据的加锁。
    如梭中断上下文和一个下半部共享数据,在访问共享数据之前,需要进制中断并得到锁的使用权。

  • 相关阅读:
    sqlserver 镜像 断开连接 正在恢复+主机服务器关机用备用镜像
    SQL SERVER 2005镜像配置(有无见证服务器都行)
    Terminal Service 终端链接
    SSL/TLS Diffie-Hellman Modulus <= 1024 位 (LogJam) 使用2048位或更高的Diffie-Hellman
    各国各种语言翻译
    Windows Server 2012上安装.NET Framework 3.5
    ALM11服务器IP变更相关配置修改
    转载:Linux下启动和关闭Weblogic(管理服务器+被管服务器)
    转载:AWR介绍使用
    安装QTP之后造成环境变量java冲突问题的解决方案
  • 原文地址:https://www.cnblogs.com/genius-sen/p/7748393.html
Copyright © 2020-2023  润新知