一、实验要求:
- 本人学号后两位为17,则寻找系统调用号为17的系统调用
- 
通过汇编指令触发该系统调用 
- 
通过gdb跟踪该系统调用的内核处理过程 
- 重点阅读分析系统调用入口的保存现场、恢复现场和系统调用返回,以及重点关注系统调用过程中内核堆栈状态的变化
二、环境搭建:
2.1按照实验一中的步骤来进行初始环境搭建
sudo apt install build-essential sudo apt install qemu sudo apt install libncurses5-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 cd linux-5.4.34
2.2配置内核选项
 make defconfig 
 make menuconfig
进入 Kernel hacking的Compile-time checks and compiler options:


进入Processor type and features:

2.3编译内核:
make -j$(nproc)
qemu-system-x86_64 -kernel arch/x86/boot/bzImage

由于没有⽂件系统最终会kernel panic,这属于正常现象。
2.4利用busybox制作根文件系统
下载并制作根文件系统
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 make -j$(nproc) && make install
在配置选项时进入Settings,选择Build static binary (no shared libs)

制作内存根文件系统镜像:
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脚本,并修改权限:
vi init #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys echo "Wellcome WangbaOS!" cd home /bin/sh chmod +x init
#打包成内存根⽂件系统镜像 find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../ rootfs.cpio.gz #测试挂载根⽂件系统,看内核启动完成后是否执⾏init脚本 qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz

三、汇编指令触发该系统调用
3.1 查询系统调用号为17为的系统调用

可以看到是 pread64:
使用手册看该函数:man pread64

从上面的描述中可以看出:
这个函数可以原子性的定位搜索(seek)和执行I/O。
返回值:成功,返回成功读取数据的字节数;失败,返回-1;
参数:
(1) fd:要读取数据的文件描述符
(2) buf:数据缓存区指针,存放读取出来的数据
(3) count:读取数据的字节数
(4) offset:读取的起始地址的偏移量,读取地址=文件开始+offset。注意,执行后,文件偏移指针不变
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
main()
{
	  char filename[100];
	  int fd;
	  char data[10];
	  fd=open("test.txt",O_RDWR);
	  if(fd==-1) printf("open error:%m\n"),exit(-1);
	  if(pread(fd,data,sizeof(data),0) < 0)
	  {
		    printf("read fail");
		    exit(-1);
	  }
	  printf("data=%s",data);
	  close(fd);
}
编译运行可以看到c程序读取test.txt文件中的数据

四、利用gdb跟踪系统调用的内核处理过程
4.1 重新制作根文件系统,并启动qemu
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio.gz cd .. qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"
接着在linux-5.4.34文件夹下打开一个终端
# 打开gdb gdb vmlinux target remote:1234 # 并在gdb中对__x64_sys_pread64进行断点 b __x64_sys_pread64

4.2 在qemu窗口运行程序并在gdb窗口进行单步调试
在qemu中执行程序
并在gdb中断点跟踪



整个流程大概如下:
用户态:
 pread64.c ----> __x64_sys_pread64 ----> ksys_pread64
内核态:
 entry_SYSCALL_64 () ----> do_syscall_64 ----> ksys_ pread64---- > do_syscall_64 ----> syscall_return_slowpath() ----> entry_SYSCALL_64 ()
 
                    
                     
                    
                 
                    
                 
         
