Linux内核分析实验四

Posted YoungX0701

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux内核分析实验四相关的知识,希望对你有一定的参考价值。

*************************************************************************

刘旸 + 原创作品转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

**************************************************************************


    在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断。系统调用就是一种中断。

    Linux中的状态分为核心态和用户态两种。当进程在执行用户自己的代码时,则称其处于用户态,当我们在系统中执行一个程序时,大部分时间是运行在用户态下的进程需要操作系统帮助完成某些它没有权力和能力完成的工作时,会通过执行系统调用等切换到内核级上运行,此时我们称进程处于内核态。


下面我们通过一个实验来观察程序是如何完成系统调用的:

1.首先在实验楼文件夹下新建一个C文件,命名为getuid.c,代码如下:


2.编译运行,结果如下:

 

可以看到该程序的执行效果就是返回当前uid

 

3.现在我们改用内嵌汇编码实现返回uid的功能,修改后的代码如下:

 


4.编译运行,结果如下:

 


改编后代码编译运行的结果与用纯C编写的代码的结果一模一样,也就是说,这段内嵌的汇编码的功能与getuid()语句的功能是一样的。

 

接下来我们用gdb调试纯C程序,看看Linux是如何完成系统调用的:

5.首先用-g命令编译getuid.c以便接下来用gdb调试程序。


6.进入gdb开始调试程序,用file命令加载需调试的文件,list命令查看代码。


7.在系统调用函数getuid()处设置断点。


8.运行程序,程序会在getuid()前暂停。


9.使用disass命令查看getuid()函数的汇编码,可以看到此时eip指针指向getuid()的第一句汇编码。


10.使用info r命令查看函数执行前各寄存器的内容,注意此时的eax=1。


11.使用ni命令执行函数的第一行指令,用disass命令可以看到指针已经往下挪了一行:


12.再次使用info r命令查看各寄存器当前的内容,我们发现此时eax中的值已经变为了199,即getuid()的系统调用号。


13.继续执行下一条指令,再次查看各寄存器的内容,此时eax中的值已经变成了1000,即当前的uid。


14.继续运行,就返回到main函数执行打印语句了。


分析与总结:

    通过对纯C的跟踪调试,我们可以得出以下结论:

    1)查看uid是只有处于0级,即内核态程序才能使用的特权,因此普通用户进程需要通过系统调用从用户态切换到内核态完成此功能。

    2)用户进程进行系统调用时使用eax传递系统调用号以将API与对应的System Service关联起来。

    3)System Service完成后,进程从内核态切换回用户态,返回的值将通过eax传递回进程的用户态堆栈。


    另外,通过纯C代码与内嵌汇编代码的比较和匹配,可以知道进程进行系统调用的过程大致如下图所示:

 


以上是关于Linux内核分析实验四的主要内容,如果未能解决你的问题,请参考以下文章

Linux内核分析实验五

Linux内核分析实验三

Linux内核分析实验五

Linux内核分析实验三

Linux内核分析实验八

Linux内核分析实验七