举例跟踪分析Linux内核5.0系统调用处理过程

学号 055
原创作品转载请注明出处 + 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
需要使用实验截图
需要仔细分析系统调用、保护现场与恢复现场、系统调用号及参数传递过程
总结部分需要阐明自己对系统调用工作机制的理解。

实验环境:

Ubuntu 18.04 LTS

实验步骤:

(1)编译内核Linux-5.0

可以从孟老师的github上clone,https://github.com/mengning/linux.git
也可以直接从Linux官方下载。
(尽量直接从官方下载压缩包,github上clone的速度难以恭维)

# 解压缩
make menuconfig # 在linux-5.0 目录下,配置编译时的配置文件
# 找到kernel hacking,->Compile-time checks and compiler options
# 选择 [*]compile the kernel with debug info
make -j4 # 编译内核
# 不出意外的话,一开始运行make -j4 是会报错的,需要仔细阅读错误原因并处理
# 一般多是缺少相应的依赖项
# 初学者不建议随意更改Ubuntu的源,我一开始网上找了个清华源的source list,安装依赖项的时候老是找不到。。。

编译时配置文件
编译时配置文件

缺少依赖项
缺少依赖项

缓慢的编译中
缓慢的编译中

如果在虚拟机,并且虚拟机不自动扩容磁盘的话,别把磁盘搞太小。。编译了半天结果提示磁盘满了。。

(2)制作根文件


mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu
gcc -pthread -o init linktable.c menu.c test.c -m32 -static
cd ../rootfs
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

(3)启动menu

qemu -kernel ~/linux5/arch/x86/boot/bzImage -initrd rootfs.img

(4)跟踪调试内核

qemu -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img -S -s -append nokaslr

运行qemu虚拟机后,在当前目录新建一个终端窗口,运行下列命令:

gdb vmlinux
target remote:1234 # 建立gdb和gdbserver之间的连接

首先,几乎所有的内核模块均会在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时间片,并且从不返回。

增加系统调用

学号后2位 55

在test.c中增加函数,_test()
重新编译rootfs.img,如下:

#include <unistd.h> 
#include <sys/reboot.h>
int _test(int argc, char *argv[])
{
    gid_t list[500];
    int x = getgroups(0,list);
    int flag;
    getgroups(x,list);
    flag = setgroups(x,list);
    printf("%d\n",flag);
    return 0;
}
int main()
{
    PrintMenuOS();
    SetPrompt("MenuOS>>");
    MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6)",NULL);
    MenuConfig("quit","Quit from MenuOS",Quit);
    MenuConfig("time","Show System Time",Time);
    MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
    MenuConfig("fcntl","FCNTL",_test);
    ExecuteMenu();
}

之后重新编译执行,当执行的返回值为0,说明执行成功。 系统调用的工作机制是:当用户态进程调用一个系统调用时,CPU切换到内核态并开始执行一个内核函数,由API、中断向量和中断处理程序协调完成。

实验总结

系统调用过程

通过这次实验,熟悉了内核调度的过程,用户态->内核态。

应用程序通过软中断来通知内核,进入系统调用入口system_call,从而执行对应的系统调用函数。

posted on 2019-03-19 16:23  cuiguohua1994  阅读(157)  评论(0编辑  收藏  举报

导航