深入理解系统调用

实验要求“

  • 找一个系统调用,系统调用号为学号最后2位相同的系统调用,学号末尾2位为10
  • 通过汇编指令触发该系统调用
  • 通过gdb跟踪该系统调用的内核处理过程
  • 重点阅读分析系统调用入口的保存现场、恢复现场和系统调用返回,以及重点关注系统调用过程中内核堆栈状态的变化

一  环境准备

  上次实验已经下载好内核源码参考https://www.cnblogs.com/russian/p/12873826.html,接下来进行内核编译选项。

  配置内核编译选项,

  首先打开debug相关选项 ;选择进入Kernel Hacking

  接着选择 Compile-time checks and compiler options --> 

  修改下列两个选项为Y

   然后关闭KASLR,否则会导致打断点失败,首先进入Processor type and features选项

 

 保存退出。

二 制作根文件系统

  1.下载跟文件系统  :

      axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2  

   tar -jxvf busybox-1.31.1.tar.bz2
   cd busybox-1.31.1 
2.制作根文件系统:
   make menuconfig
   编译成静态链接,不用动态链接库:在setting中设置

     然后编译安装,默认会安装到元年吗目录下_install目录中;

    make -j$(nproc) && make install
 3.接着制作内存根文件系统镜像
    mkdir rootfs
    cd rootfs
    cp ../busybox-1.31.1/_install
/* ./ -rf
    mkdir dev proc sys home
    
sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/
 
4.准备添加init脚本文件放根目录下,
    touch init.sh
    vi init.sh
    i键入内容如下:
     #!/bin/sh
     mount -t proc none /proc mount -t sysfs none /sys
     echo "Wellcome MengningOS!" echo "--------------------"
     cd home
     /bin/sh
    保存退出 :wq

    接着给init脚本添加可执行权限: chmod +x init
    打包成内存根文件系统镜像:find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
    测试挂在根文件系统,看内核启动完是否执行脚本:
qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz
    最终挂载成功之后显示
三 系统调用
  1.查看系统调用
    打开内核源码中中断调用号,找到与自己学号末尾相同的中断服务例程,目录为linux-5.4.34/arch/x86/entry/syscalls/syscall_64.tbl

可知第10号调用为mprotect ,对应的处理函数为__x64_sys_mprotect。


    2.编写汇编调用代码


     由于我们搭建的系统不支持动态链接,因此这里我们在使用gcc编译时要用-static静态编译参数)。

    gcc test.c -o test -static

    3.重新执行根文件系统(重新打包,用qemu运行)

    find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz
    qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz

   四  gdb调试。

    1. 启动gdb调试

    首先命令行启动qemu:    

    qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"
   然后重新开一个命令行,在源码目录下启动gdb
    gdb vmlinux
   接着在gdb中运行:
target remote:1234
  

   然后给对应大的系统调用打上断点

   如图成功触发断点。

   2.gdb单步调试

    

     

   五 结果分析‘

    系统调用的保存现场和恢复现场;entry_SYSCALL_64是系统调用的入口点,它完成了保存现场,调用对应的内核处理函数、恢复现场、系统调用返回等工作。

    

       汇编指令syscall 触发系统调用,通过MSR寄存器找到了中断函数入口;

                   

  可以看到,它没有使用sava_all命令保存现场,而使用了特殊的swapgs,来快照式地保存现场,加快了系统调用的速度。

               

     接着跳转获得系统调用号,执行系统调用的内容

              

       调用结束,恢复到用户态执行syscall_return_slowpath 函数要为恢复现场做准备

    

       swapgs——恢复现场

 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/russian/p/12963046.html