zoukankan      html  css  js  c++  java
  • 深入理解系统调用

    一.实验要求:

    1.找一个系统调用,系统调用号为学号最后2位相同的系统调用

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

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

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

    二.配置实验环境:

    1,下载工具、Linux内核源码

    sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev
    sudo apt install axel
    axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/ linux-5.4.34.tar.xz 
    xz -d linux-5.4.34.tar.xz
    tar -xvf linux-5.4.34.tar

    2.配置内核编译选项

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

     3.编译运行内核

    make -j$(nproc) # nproc gives the number of CPU cores/threads available
    # 测试⼀下内核能不能正常加载运⾏,因为没有⽂件系统终会kernel panic
    qemu-system-x86_64 -kernel arch/x86/boot/bzImage  #  此时应该不能正常运行,会报kernel pannic错误,因为没有文件系统。

    4.制作内存根文件系统

    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/<br>

    将init脚本放入该目录下,然后执行:

     a打包成内存根文件系统镜像

    b测试挂载根文件系统,看内核启动完成后是否执行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

     看到Wellcome os!说明成功执行了init脚本

    三.用汇编代码编写系统调用程序

    1.学号后两位为44,查看syscall_64.tbl对应系统调用为sendto,如下图所示;

     sendto系统调用用于向指定的目的地址发送数据

    2.这里写一个test_sendto.c文件,调用44号系统调用:

    #include<stdio.h>
    int main()
    {
        asm volatile(
        "movl $0x2c,%eax
    	" //使⽤EAX传递系统调⽤号44
        "syscall
    	" //触发系统调⽤ 
        );
        printf("sendto
    ");
        return 0;
    }

    3.用gcc静态编译,生成可执行文件

    gcc -o test_sendto test_sendto.c -static

    4.将文件放至rootfs/home路径下,重新执行如下两条语句:

    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.启动qemu

    qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -s -S

    2.新打开一个终端命令分别执行如下步骤

    cd linux-5.4.34/ # 切到对应的文件夹
    gdb vmlinux
    (gdb) target remote:1234

    3.根据前面提到的,44号系统调用的内核处理函数为__x64_sys_sendto,因此我们给它打上断点: b __x64_sys_sendto,如下图

    4.保存现场:

    可以看到保存现场使用了特殊的swapgs,加快了系统调用的速度,swapgs之后push了一堆寄存器,将其入内核堆栈,然后转换成pt_regs结构体

    5.现场恢复

     执行了一个宏USERGS_SYSRET64, 在linux5.4.34/arch/x86/include/asm/irqflags.h中有他的如下定义

    swapgs——恢复现场和sysretq——系统调用返回。

     五.总结

    应用程序调用API,然后trap陷入,进入系统调用,进入内核态,保存现场执行中断处理程序 然后恢复现场返回用户态。其中保存现场和恢复现场都是通过操作内核的堆栈实现的

  • 相关阅读:
    Web前端开发
    用javascript向一个网页连接接口发送请求,并接收该接口返回的json串
    如何在tomcat启动的时候运行一个Java类
    Linux永久挂载远程网络目录
    C/C++跨平台的的预编译宏
    利用http实现文件的上传和下载
    基于qml创建最简单的图像处理程序(1)-基于qml创建界面
    基于qml创建最简单的android机图像采集程序
    OpenCV相关网站推荐(Informative websites related to OpenCV)
    (GO_GTD_3)基于OpenCV和QT,建立Android图像处理程序
  • 原文地址:https://www.cnblogs.com/wwwxuexi/p/12977234.html
Copyright © 2011-2022 走看看