深入理解系统调用

1.系统调用的概念

用户态与内核态:

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

 

32 位 Linux 进程地址空间:

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

 

系统调⽤概述:

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

 

 Linux的系统调⽤:

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

 

 2.环境准备

编译选项:

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

 

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

 

 编译内核并运行:由于还未挂载根文件系统,因此出现kernel panic。

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

 

 制作根文件系统:

配置编译选项:

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

 

 编写init脚本:

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

 

 打包根文件系统镜像:

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

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

 

 3.系统调用分析

本人学号末2位为95,查看95号系统调用:

 

 umask用于设置文件和目录的默认访问权限。

 

编写代码调用这一系统调用:

int main()
{
  asm volatile(
  "movl $0x5f,%eax\n\t" 
  "syscall\n\t" );
  return 0;
}

静态编译后将可执行文件拷贝到rootfs/home目录下,重新生成根文件系统。

再次运行虚拟机,可以发现已经成功拷贝该文件。

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

 

进行跟踪调试:

由于umask对应的内核处理函数为 __x64_sys_umask,因此在__x64_sys_umask处断点。

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

 

 查看函数调用堆栈:

 

不难发现,entry_SYSCALL_64是系统调用的入口,完成 保存现场的功能。进入该函数:

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

 

 swapgs指令用于保存现场。这是在x86-64中引入的指令,类似快照的⽅式将保存现场和恢复现场时的CPU寄存器也通过CPU内部的存储器快速保存和恢复,近⼀步加快了系统调⽤。

继续运行,回到do_syscall函数,这个

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

 

 可以发现,rax存储了系统调用号。通过系统调用表调用相应的系统调用函数,然后将返回值存入rcx寄存器中。

继续执行,回到entry_SYSCALL_64函数中,这一部分的代码用于恢复现场。

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

 

 4.总结

系统调用的流程大致如下:

首先,通过汇编指令中的系统调用号找到系统调用入口ENTRY(entry_SYSCALL_64),然后在ENTRY(entry_SYSCALL_64)中,执行swapgs保存现场。随后执行do_syscall_64方法,该方法中,执行x32_sys_call_table方法,根据rax中存储的系统调用号跳转至具体的系统调用函数,在本例中,为__x64_sys_umask。系统调用函数执行完毕后,返回ENTRY(entry_SYSCALL_64)方法,执行恢复现场操作。

 

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