分析 system_call 中断处理过程
重新定义getpid和getppid
- 首先进入shiyanlou的/LinuxKernel目录,使用git命令进行代码克隆。
- 之后使用vim,对test.c的代码进行修改,具体修改如下:
首先声明getpid和getppid的代码
int _20242817_main1(){
pid_t pid=getpid();
pid_t ppid=getppid();
printf("pid=%d ppid=%d\n",pid,ppid);
}
int _20242817_main2() {
pid_t pid, ppid;
asm volatile("mov $0x14, %%eax\n\t"
"int $0x80\n\t"
"mov %%eax, %0\n\t"
: "=r" (pid) :: "%eax");
asm volatile("mov $0x40, %%eax\n\t"
"int $0x80\n\t"
"mov %%eax, %0\n\t"
: "=r" (ppid) :: "%eax");
printf("pid=%d ppid=%d\n", pid, ppid);
return 0;
其次是在main()函数中添加如下代码
MenuConfig("getpid1","system_call_1",_20242817_main1);
MenuConfig("getpid_asm_2","system_call_asm_2",_20242817_main2);
- make编译后,启动test。调用getpid1和pid_asm_2,可以成功使用。
使用gdb进行追跟踪分析
- 在LinuxKernel目录中使用命令:qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S来启动冻结的内核。
- 另外打开一个Shell,使用gdb对进程进行跟踪分析。进行gdb调试,建立gdb和gdbserver之间的连接,并在getpid函数处设置断点,
在设置断点后,我们发现sys_getpid函数位于kernel/sys.c文件的第817行。当我们在gdb中输入c命令以继续运行内核时,之前冻结的内核开始执行,并且getpid1能够正常运行。然而,当我们尝试运行getpid_asm_2时,GDB会在sys_getpid处显示断点,并且无法继续执行下一步操作。同时,在MenuOS中,getpid_asm_2的运行也会卡住,无法继续进行。
经过分析和查阅相关资料,在使用int $0x80汇编指令触发系统调用时,gdb无法正常跟踪系统调用。int $0x80是一种传统的触发系统调用的方法,但当系统调用进入内核态时,gdb默认只跟踪用户态的代码,无法继续跟踪。
流程图
当计算机上执行int 0x80指令时,CPU会跳转到system_call函数开始处理系统调用。这个过程首先会保存当前的上下文,然后通过syscall_call和syscall_after_call等函数进行系统调用的处理和参数传递。如果需要,syscall_exit_work函数会处理信号调度。最后,通过restore_all函数恢复上下文,并通过irq_return返回到用户空间,继续执行程序。这一系列操作确保了系统调用的正确执行和用户空间的顺利恢复。
实验总结
在本次实验中,我通过gdb深入分析了Linux操作系统中系统调用的完整流程,从系统调用的起点system_call一直到执行iret指令返回用户态。以下是我们对实验的回顾和一些核心要点。系统调用是用户程序与内核交互的关键通道,它使得用户程序能够请求内核提供的服务。实验中,我们选定了一个特定的系统调用并通过gdb设置了断点,从system_call这个入口点开始我们的分析。在这个过程中,gdb成为了我们不可或缺的工具,它让我们能够逐层深入,跟踪函数的调用链,监测参数的传递和上下文的转换。系统调用触发时,CPU通过中断机制从用户态切换到内核态。system_call函数作为系统调用的集中处理点,它负责识别系统调用编号,并将执行流程导向相应的内核处理程序。通过细致的单步跟踪,我们能够清晰地观察到内核如何根据系统调用编号找到对应的处理程序,以及如何处理传入的参数和返回值。在跟踪过程中,我还注意到内核执行了权限检查,以确保用户程序有执行请求操作的权限,这是维护系统安全的重要环节。之后,内核执行具体的业务逻辑,这可能包括文件处理、进程控制或网络通信等。在这个过程中,内核可能需要进行内存管理、任务调度等操作,这些细节的观察对于理解系统调用的复杂性至关重要。最终,当内核完成对请求的处理后,它通过iret指令将控制权交还给用户空间,恢复用户程序的执行状态,包括寄存器和标志位等,使得用户程序能够继续执行并接收到内核的响应结果。
“20242817李臻 原创作品转载请注明出处 《Linux内核分析》《Linux内核分析》MOOC课程Linux内核分析MOOC课程”