标签: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