深入理解系统调用

实验内容:

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

本人学号为SA19225403

故查找系统调用号为03的系统调用

深入理解系统调用

 

由上图可知3号系统调用为__x64_sys_close

在Linux开发者手册中查找函数close

深入理解系统调用

可知要调用该函数需要

#include<unistd.h>

函数参数为int型变量的文件描述符。

函数用于将此文件描述符关闭,使之不再指向任何文件。

函数执行成功将返回0,失败将返回-1。

 

一、实验环境准备

实验环境沿用实验一的环境

配置内核选项:

 make defconfig 
 make menuconfig

深入理解系统调用

 

 

 选择进入kernel hacking的子菜单

深入理解系统调用

 

 

 选择进入compile-time checks and compiler options的子菜单

深入理解系统调用

 

 

 选中如图选项,退回到初始的主菜单界面

深入理解系统调用

 

 

 进入processor type and features子菜单

深入理解系统调用

 

 

 将如图选项exclude

 

之后编译内核

make -j$(nproc)
qemu-system-x86_64 -kernel arch/x86/boot/bzImage

深入理解系统调用

 

 

 

接下来着手制作根文件系统

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
make menuconfig

安装busybox并修改设置

深入理解系统调用

 

 

 进入setting子菜单

深入理解系统调用

 

 

 选中build static binary

保存退出后执行编译

make -j$(nproc) && make install

接下来制作根文件系统镜像并挂载

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/

编写init脚本并为之添加可执行权限

#!/bin/sh
mount -t proc none /proc mount -t sysfs none /sys
echo "WWWWWWrrrrrryyyyyyyyy"
cd home
/bin/sh

打包成镜像

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

测试挂载

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd rootfs.cpio.gz

深入理解系统调用

 

 

二、系统调用

接下来我们编写一段简单的代码来调用close函数

在根文件系统目录rootfs下创建文件close.c

深入理解系统调用

编写完之后编译运行一下

gcc -o close close.c -static

./close

深入理解系统调用

 

之后将代码改写为内嵌汇编的代码,使用汇编代码来替换close函数

 深入理解系统调用

 深入理解系统调用

 

 

 继续编译测试一下,一切正常

 

 

 

接下来我们将利用gdb来跟踪系统调用的内核处理过程

重新制作根文件系统的镜像

find . -print0 | cpio --null -ov --format=newc | gzip -9 > new_rootfs.cpio.gz
cd ..
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd new_rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"

深入理解系统调用

 

 由于这次的qemu指令中加入了-nographic选项,所以不会有界面弹出

之后再打开一个终端启动gdb输入

gdb vmlinux

深入理解系统调用

 

target remote:1234

输入上述指令连接gdb server

再输入c,使虚拟机继续运行

深入理解系统调用

 

 尝试在qemu中运行asmclose

深入理解系统调用

 

 

在gdb中对3号系统调用打断点

b __x64_sys_close

 深入理解系统调用

 然后在qemu中再次./asmclose

在gdb中逐步键入n键进行单语句的调试

深入理解系统调用

 深入理解系统调用

 

三、分析

现在我们来重点阅读分析系统调用入口的保存现场、恢复现场和系统调用返回

深入理解系统调用

 系统调用过程中寄存器的用途如下:

深入理解系统调用

 

 

函数do_syscall_64:可以推测该函数用以获取系统调用号并存放至rax寄存器中

深入理解系统调用

 

 深入理解系统调用

 

函数syscall_return_slowpath负责启用中断以及捕获异常系统调用

每个系统调用在启用中断的情况下调用。 此外,它还必须在启用了中断的情况下返回。

任何有问题的syscall实现都会被syscall_return_slowpath捕获

深入理解系统调用

触发系统调用之后,也即调用函数entry_SYSCALL_64之后,系统在进入内核之前将syscall之后的指令的地址存储到RCX中(详见arch/x86/entry/entry_64.S)

深入理解系统调用

 

 

同时调用swapgs 指令保存现场,swapgs指令如下:

深入理解系统调用

 

 

 

深入理解系统调用

 系统调用返回的详细过程见下:

深入理解系统调用

 

上一篇:4. 镜像的原理


下一篇:Linux-文件系统-学习笔记(14):根文件系统原理与nfs搭建方法