深入理解系统调用

配置环境
1.安装编译工具和qemu虚拟机
sudo apt install build-essential libncurses-dev bison flex libssl-dev libelf-dev
sudo apt install qemu
sudo apt install axel

2.下载内核源码和busybox,分别解压

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 
axel -n 20 https://busybox.net/downloads/busybox-1.31.1.tar.bz2
tar -jxvf busybox-1.31.1.tar.bz2

3.配置编译内核生成bzImage文件

cd linux-5.4.34
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)
make -j$(nproc) 

4.制作根文件系统

cd busybox-1.31.1
make menuconfig #记得要编译成静态链接,不⽤动态链接库。 Settings
---> [*] Build static binary (no shared libs) #然后编译安装,默认会安装到源码⽬录下的 _install ⽬录中。 make -j$(nproc)
make install

5.制作根文件系统镜像

cd ..
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/

在roofs根目录下创建init文件,init文件内容如下:

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

复制代码

给init脚本添加可执行权限

chmod +x init

将根文件系统打包为镜像


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

此时运行qemu,测试挂载根⽂件系统,看内核启动完成后是否执⾏init脚本

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

运行成功,环境就此搭建完成

 

编写系统调用测试程序,放入根文件系统中,重新打包镜像

我的学号最后两位是12,到linux-shiyan2/linux-5.4.34/arch/x86/entry/syscalls中的syscall_64.tbl文件中查看系统调用号12的系统调用

12对应brk系统调用,brk用于实现虚拟内存到内存的映射,在roofs/home下创建test.c文件,测试代码如下:

#include<stdio.h>

#include<unistd.h>

 

int main()

{

    int *p = sbrk(0);

    brk(p+1);/* 3 使用brk分配空间 */

    *p = 1;

    printf("%d\n",*p);

    brk(p);      /*4 使用brk释放空间 */

    *p = 2;

    printf("%d\n",*p);

 

    return 0;

}

静态编译test.c,生成test

gcc -o test test.c -static

返回到roofs目录下,重新打包镜像文件,启动qemu,可以看到test.c和test

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 -S -s

进行gdb调试

执行下面命令

qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s -nographic -append "console=ttyS0"

打开一个新的中断,执行命令,打上断点,进行单步调试

cd linux-5.4.34
gdb vmlinux
target remote:1234
b __x64_sys_brk

 

 可以看到函数调用过程,__x64_sys_brk  ---> do_syscall_64 --->entry_SYSCALL_64 --->syscall_return_via_sysret

 

posted @ 2020-05-27 22:41  zhouxinghui  阅读(190)  评论(0编辑  收藏  举报