标签:table init 生成 call 代码 汇编指令 mic idt 用户
1.系统调用的概念
用户态与内核态:

32 位 Linux 进程地址空间:

系统调?概述:

Linux的系统调?:

2.环境准备
编译选项:


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

制作根文件系统:
配置编译选项:

编写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.系统调用分析
本人学号末2位为95,查看95号系统调用:

umask用于设置文件和目录的默认访问权限。
编写代码调用这一系统调用:
int main()
{
asm volatile(
"movl $0x5f,%eax\n\t"
"syscall\n\t" );
return 0;
}
静态编译后将可执行文件拷贝到rootfs/home目录下,重新生成根文件系统。
再次运行虚拟机,可以发现已经成功拷贝该文件。

进行跟踪调试:
由于umask对应的内核处理函数为 __x64_sys_umask,因此在__x64_sys_umask处断点。

查看函数调用堆栈:

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

swapgs指令用于保存现场。这是在x86-64中引入的指令,类似快照的?式将保存现场和恢复现场时的CPU寄存器也通过CPU内部的存储器快速保存和恢复,近?步加快了系统调?。
继续运行,回到do_syscall函数,这个

可以发现,rax存储了系统调用号。通过系统调用表调用相应的系统调用函数,然后将返回值存入rcx寄存器中。
继续执行,回到entry_SYSCALL_64函数中,这一部分的代码用于恢复现场。

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)方法,执行恢复现场操作。
标签:table init 生成 call 代码 汇编指令 mic idt 用户
原文地址:https://www.cnblogs.com/daiyan1/p/12952508.html