深入理解Linux系统调用

1、系统调用号查询

打开/linux-5.4.34/arch/x86/entry/syscalls/syscall_64.tbl,查看要选择进行实验的系统调用。系统调用为mlockall。

 mlockall() 将进程使用的部分或者全部的地址空间锁定在物理内存中,防止其被交换到swap空间。有些对时间敏感的应用会希望全部使用物理内存,以提高数据访问和操作的效率。

 

2、实验环境搭建

make menuconfig  

勾选Compile the kernel with debug info,并且关闭KASLR

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

勾选Bulid static binary (no shared libs)

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 "Wellcome MyOS!"
 echo "--------------------" 
 cd home
 /bin/sh 

给init添加权限

chmod +x 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

 

3、汇编语言调用

#include
#include

int main(){
        int o;
        o=mlockall(MCL_CURRENT);
        printf("out:%d\n",o);
        return 0;
}

 

 然后静态编译

gcc -o gsn gsn.c -static

改写触发系统调用

#include
#include

int main(){
        int o;
        int i;
        asm volatile(
            "movq $0x1, %%rdi\n\t"
            "movl $0x97, %%eax\n\t"
            "syscall\n\t"
            "movq %%rax, %0\n\t"
            :"=m"(o)
            :"g"(in)
)
        printf("out: %d \n",o)
        return 0;
}        

编译后查看结果

 

 

4、gdb调试与分析

启动虚拟机

 

 并且在另一个终端开启调试

深入理解Linux系统调用_第1张图片

 

 连接进行调试

 

 gdb输入命令c

 

 深入理解Linux系统调用_第2张图片

 

 在gdb函数入口做断点,监听,然后在虚拟机中执行gsn

 

 断点定位到端口799

深入理解Linux系统调用_第3张图片

 

 

执行完这个函数,到do_sys_call_64 中 ,接下来为要执行的 syscall_return_slowpath 函数恢复现场

 

继续执行,再次entry_SYSCALL_64 ,接下来执行用于恢复现场的汇编指令,最后popq出栈指令,恢复了rdirsp寄存器,系统调用完成

 

5、总结

触发系统调用后,通过调用swapgs和压栈保存了现场,然后通过do_syscall_64 函数,在ax寄存器中得到系统调用号,然后去执行系统调用。再完成执行现场的恢复,然后出栈指令恢复原 rdi 和 rsp的内容,也就是完成了堆栈的切换。

 

你可能感兴趣的:(深入理解Linux系统调用)