• 深入理解系统调用


    深入理解系统调用

    准备工作

    下载并解压kernel
    1 #之前已下载过直接解压即可
    2 xz -d linux-5.4.34.tar.xz 
    3 tar -xvf linux-5.4.34.tar 
    4 cd linux-5.4.34

    配置内核选项

     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 
     8  [*] Kernel debugging 
     9  # 关闭KASLR,否则会导致打断点失败
    10  Processor type and features ----> 
    11  [] Randomize the address of the kernel image (KASLR)

    编译并测试能否使用qemu启动内核

    1 make -j
    2 qemu-system-x86_64 -kernel arch/x86/boot/bzImage

    此时由于没有文件系统,所以最终kernel panic==》需要制作根文件系统

    使用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
    4 make menuconfig 
    5 [*] Build static binary (no shared libs)#设置编译成静态链接
    6 make -j$(nproc) && make install #编译并安装

      制作根文件系统的镜像

     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/
     6 在根目录下添加init脚本,内容如下:
     7  #!/bin/sh 
     8  mount -t proc none /proc 
     9  mount -t sysfs none /sys 
    10  echo "Wellcome MengningOS!" 
    11  echo "--------------------" 
    12  cd home 
    13  /bin/sh
    14  赋予其可执行权限
    15  chmod +x init

    把根文件系统打包生成rootfs.cpio.gz

    qemu-system-x86_64 -kernel /home/lmm/下载/linux-5.4.34/arch/x86/boot/bzImage  -initrd rootfs.cpio.gz #在rootfs启动

    根据显示结果可得:执行了init脚本。

    测试能否使用gdb跟踪调试

    bash1:

    1 qemu-system-x86_64 -kernel /home/lmm/下载/linux-5.4.34/arch/x86/boot/bzImage -initrd  rootfs.cpio.gz -S -s #-s,在TCP 1234端⼝上创建了⼀个gdbserver -S 启动时暂停虚拟机,等待 gdb 执⾏ continue指令

    bash2:

    1 cd linux-5.4.34/ 
    2 gdb vmlinux 
    3 (gdb) target remote:1234 
    4 (gdb) b start_kernel
    5 (gdb) c

    可以看到可成功调试。

    汇编指令触发该系统调用并通过gdb跟踪该系统调用的内核处理过程

    系统调用的过程图

    学号19225224,选择24号系统调用

    ched_yield()会主动放弃当前CPU给其他进程使用;但是如果当前CPU上无其他进程等待执行,则直接返回继续执行当前进程。

    调用sched_yield()之后当前进程会被移动到进程优先级等待队列尾部,让相同或者更高优先级进程运行。

    在rootfs/home下添加test[汇编文件],通过该程序调用该系统调用

    1 int main()
    2 {
    3     asm volatile(
    4     "movl $18,%eax
    	" 
    5     "syscall
    	"  
    6     );
    7     return 0;
    8 }

    重新打包内存根文件的系统镜像

    find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz

    首先在gdb出给该系统调用出打上断点,然后在qemu上执行该test看是否会执行该系统调用。

    可以看到确实执行到该系统调用出停止了。

    具体的调用栈,依次为entry_SYSCALL_64[中断函数的入口],do_syscall_64[获取调用号,前往系统调用函数],__x64_sys_sched_yield[24号系统调用函数]

    然后继续单步执行,到了entry_SYSCALL_64 , 开始进行恢复现场

    最后的pop rsp与pop rdi进行堆栈的切换,从而结束系统调用。

    总结:

    1.首先,test程序填充系统调用的寄存器,然后syscall出发系统调用,找到中断入口函数entry_syscall_64,主要是做准备工作.由用户态转到内核态, 并做一些准备工作, 保持用户态的信息(堆栈, 寄存器)待系统调用完之后恢复现场.初始化内核, 寄存器,堆栈 等等.

    2.entry_SYSCALL_64 调用do_syscall_64[获取调用号,前往系统调用函数],然后通过eax的值到达真正的系统调用。3.系统调用完成, 恢复现场(通用寄存器, 旧的栈. flags).

     

  • 相关阅读:
    JVM优化系列之一(-Xss调整Stack Space的大小)
    被kill问题之2:Docker环境下Java应用的JVM设置(容器中的JVM资源该如何被安全的限制)
    docker的坑
    docker容器内存占用 之 系统cache,docker下java的内存该如何配置--temp
    查看docker容器的内存占用
    使用Java监控工具出现 Can't attach to the process
    使用docker查看jvm状态,在docker中使用jmap,jstat
    在Docker中监控Java应用程序的5个方法
    HDU2552 三足鼎立 【数学推理】
    C++面向对象模型
  • 原文地址:https://www.cnblogs.com/tlxclmm/p/12976966.html
Copyright © 2020-2023  润新知