深入理解系统调用

一、实验内容

1使用94号系统调用

2.通过汇编指令触发系统调用

3.通过gdb跟踪该系统调用的内核处理过程

4.阅读分析系统调用入口的保存现场、恢复现场和系统调用返回,以及关注系统调用过程中内核堆栈状态的变化

 

二、环境搭建

1、安装开发工具

1 sudo apt install build-essential
2 sudo apt install qemu 
3 sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev
4 sudo apt install axel

2、下载内核源码

1 axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz
2 xz -d linux-5.4.34.tar.xz
3 tar -xvf linux-5.4.34.tar cd linux-5.4.34

3、配置内核选项

复制代码
 1 make defconfig #Default configuration is based on 'x86_64_defconfig'
 2 make menuconfig
 3 //打开debug相关选项
 4 Kernel hacking --->
 5     Compile-time checks and compiler options --->
 6         [*] Compile the kernel with debug info
 7         [*] Provide GDB scripts for kernel debugging [*] Kernel debugging
 8 //关闭KASLR,否则会导致打断点失败
 9 Processor type and features ---->
10     [] Randomize the address of the kernel image (KASLR)
复制代码

4、编译和运行内核

1 make -j$(nproc)
2 //测试一下内核能不能正常加载运行,因为没有文件系统最终会kernel panic
3 qemu-system-x86_64 -kernel arch/x86/boot/bzImage //此时应该无法正常运行

 

 5、制作根文件系统

下载 busybox源代码解压

1 axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2
2 tar -jxvf busybox-1.31.1.tar.bz2
3 cd busybox-1.31.1

配置编译 并安装

1 make menuconfig
2 记得要编译成静态链接,不用动态链接库。
3 Settings --->
4     [*] Build static binary (no shared libs)
5 然后编译安装,默认会安装到源码目录下的 _install 目录中。
6 make -j$(nproc) && make install

6、制作内存根文件系统镜像

1 mkdir rootfs
2 cd rootfs
3 cp ../busybox-1.31.1/_install/* ./ -rf
4 mkdir dev proc sys home
5 sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/

7、 准备init脚本文件放在根文件系统跟目录下(rootfs/init),添加如下内容到init文件。

1 #!/bin/sh
2 mount -t proc none /proc mount -t sysfs none /sys
3 echo "Wellcome MengningOS!" echo "--------------------"
4 cd home
5 /bin/sh
8、给init脚本添加可执行权限
1 chmod +x init
打包成内存根文件系统镜像
1 find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
深入理解系统调用_第1张图片
 
查看系统调用
深入理解系统调用_第2张图片

查看文档可知94号系统调用为lchown。对应的内核处理函数为__x64_sys_lchown。作用:修改文件所有者和组别。触发这一系统调用,我们需要写一个小程序。使用内联汇编小程序test1.c如下:

复制代码
int main()
{
    asm volatile(
    "movl $0x5E,%eax\n\t" //使⽤EAX传递系统调⽤号94
    "syscall\n\t" //触发系统调⽤ 
    );
    return 0;
}
复制代码
9、使用gcc静态编译,并重新打包
1 gcc -o test1 test1.c -static
2 find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
可以看到,文件已编译成功
深入理解系统调用_第3张图片
深入理解系统调用_第4张图片
10、执行下列命令,进行gdb调试。
复制代码
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"

#开启新的terminal

cd linux-5.4.34
gdb vmlinux
target remote:1234
#设置断点
b __x64_sys_lchown
深入理解系统调用_第5张图片
 
11、进行gdb单步调试
深入理解系统调用_第6张图片
 
深入理解系统调用_第7张图片
 
深入理解系统调用_第8张图片
 
三、结果分析
1. 汇编指令syscall 触发系统调用,通过MSR寄存器找到了中断函数入口

 

 用户态程序触发系统调用-》然后系统进入内核态,完成内核初始化-》调用entry_SYSCALL_64 ()。通过 swapgs 指令保存现场

深入理解系统调用_第9张图片
 

 然后,执行了do_syscall_64这一内核函数,跳转获得系统调用号,执行系统调用的内容

深入理解系统调用_第10张图片

 

 

调用结束,恢复到用户态执行 syscall_return_slowpath 函数要为恢复现场做准备。
深入理解系统调用_第11张图片
 
深入理解系统调用_第12张图片
最后swapgs——恢复现场。
 

你可能感兴趣的:(深入理解系统调用)