跟踪分析Linux内核5.0系统调用处理过程
原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/
实验要求
举例跟踪分析Linux内核5.0系统调用处理过程
- 编译内核5.0
- qemu -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img
- 选择系统调用号后两位与您的学号后两位相同的系统调用进行跟踪分析
https://github.com/mengning/menu- 给出相关关键源代码及实验截图,撰写一篇博客(署真实姓名或学号最后3位编号),并在博客文章中注明“原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ ”,博客内容的具体要求如下:
- Ubuntu 18.04
- gcc
实验步骤
一 编译内核5.0
方法 下载内核、解压、make
内核下载地址:https://github.com/mengning/linux.git,此内核是中科大孟宁教授,也是国内顶级的linux内核专家,拉出的内核分支,单独由于教学使用。
命令如下
note:编译的时候可能会出现有些依赖库未找到,需要我们去手动安装,我编译的时候就遇到了两个问题
遇到了这个错误:Unable to find the ncurses libraries,然后可以sudo apt insatll ncurses-dev解决,但是在我sudo apt install的时候,遇到了这个死锁错误,如下,网上搜了一下,结局了
12345 E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)E: Unable to lock the administration directory (/var/lib/dpkg/), is another process using it?# 解决方法:ps -A | grep aptsudo kill -9 processnumber
make完之后,我们需要将git上的一个根文件系统下载下来打包成img文件
二 然后启动MenuOS系统
qemu -kernel ~/linux5/arch/x86/boot/bzImage -initrd rootfs.img
三 跟踪调试内核启动
qemu -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img -S -s -append nokaslr
注意:如果不加-append nokaslr选项,start_kernel断点有可能断不住!!!
具体如下图
首先,几乎所有的内核模块均会在start_kernel进行初始化。在start_kernel中,会对各项硬件设备进行初始
化,包括一些page_address、tick等等,直到最后需要执行的rest_init中,会开始让系统跑起来。
那rest_init这个过程中,会调用kernel_thread()来创建内核线程kernel_init,它创建用户的init进程,初始化内核,并设置成1号进程,这个进程会继续做相关的系统初始化。
然后,start_kernel会调用kernel_thread并创建kthreadd,负责管理内核中得所有线程,然后进程ID会被设置为2。
最后,会创建idle进程(0号进程),不能被调度,并利用循环来不断调号空闲的CPU时间片,并且从不返回。
增加系统调用
根据学号后两位44,在/usr/include/asm/unistd_32.h中可查得#define __NR_prof 44。
在test.c中增加函数,Prof()。
重新编译制作rootfs.img
下面是运行的结果
从结果来看,已经调用成功,但是由于Prof系统函数我没有找到函数详解,下次补上。
实验结果分析
系统调用的触发及参数传递
- 当调用一个系统调用时,CPU从用户态切换到内核态并开始执行一个system_call和系统调用内核函数。在Linux中通过执行int 0x80来触发系统调用,内核为每个系统调用分配一个系统调用号,用户态进程必须明确指明系统调用号,需要使用EAX寄存器来传递。
- 系统调用可能需要参数,但是不能通过像用户态进程函数中将参数压栈的方式传递,因为用户态和内核态有不同的堆栈,必须通过寄存器的方式传递参数。
- 概括:EAX用来传递系统调用号,EBX、ECX、EDX、ESI、EDI、EBP用来传递参数,若参数较多,则把指向内存的指针存入寄存器。
系统调用流程
参考网络资料