1. 首页
  2. IT资讯

分析system_call中断处理过程

2019独角兽企业重金招聘Python工程师标准>>> 分析system_call中断处理过程

最初版本的MenuOS只支持version和help命令,显然这并不能满足我们的需求。我们现在来为它添加一个fork命令和fork-asm命令,其作用是测试fork的系统调用。

要增加一个命令也并不难,只需要~/LinuxKernel/linux-3.18.6/menu/test.c里的main函数中添加下面一行,然后添加它的实现(需要定义在main函数前面)就可以了。

MenuConfig("fork","Test system call fork",Fork);

最后一个参数Fork是一个函数指针,也就是我们对它的定义:

int Fork(int argc, char *argv[]) {     pid_t fpid;     int count = 0;     fpid = fork();     printf("Now pid = %dn", fpid);     if(fpid < 0)         printf("Error in fork!");     else if(fpid == 0){         printf("I am the child process, my process id is: %dn", getpid());         count++;     }     else{         printf("I am the parent process, my process id is: %dn", getpid());         count++;     }     printf("Now count = %dn", count);     return 0; }

同样的方法,也可以添加ForkAsm函数与命令(在我的上一篇博文《Linux下嵌入汇编代码调用API  using fork()》中就有Fork()与ForkAsm()的实现,只要改下函数名就好了)。

现在,我们来通过gdb调试一下我们刚刚添加的命令从调用到运行结束的过程:

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

打开另外一个终端,启动gdb,我们来链接内核并添加断点:

(gdb) file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表 (gdb) target remote:1234 # 建立gdb和gdbserver之间的连接,按c让qemu上的Linux继续运行 (gdb) break start_kernel # 断点的设置可以在target remote之前,也可以在之后 (gdb) break sys_fork     # sys_fork是fork的系统调用入口

现在我们按c让内核启动,启动完成后我们在help里看一看fork和fork-asm有没有被加进去:分析system_call中断处理过程

可以看到,现在这两个命令应该都可以用了,我们来试一试fork-asm:分析system_call中断处理过程

可以看到,系统调用sys_fork()时就到了我们设置的断点,我们来继续单步调试:分析system_call中断处理过程

接下来我们分析一下system_call的具体调用过程,详细代码见/kernel/entry_32.S

分析system_call中断处理过程

这段汇编代码较为复杂,还是来看一下简化版本的吧:

.macro INTERRUPT_RETURN  ; 中断返回     iret .endm .macro SAVE_ALL          ; 保护现场     ... .macro RESTORE_INT_REGS     ... .endm   ENTRY(system_call)     SAVE_ALL syscall_call:     call *sys_call_table(,%eax,4)     movl %eax, PT_EAX(%esp)  ; store the return value syscall exit:     testl $_TIF_ALLWORK_MASK, %ecx # current->work     jne syscall_exit_work restore_all:     RESTORE_INT_REGS irq_return:     INTERRUPT_RETURN      ; 到这里就算执行完了 ENDPROC(system_call)   syscall_exit_work:     testl  $_TIF_WORK_SYSCALL_EXIT, %ecx     jz work_pending END(syscall_exit_work)   work_pending:     testb $_TIF_NEED_RESCHED, %cl     jz work_notifysig work_resched:     call schedule     jz restore_all work_notifysig:     ...                  ; deal with pending signals END(work_pending)

画了一个流程图,见笑见笑~

分析system_call中断处理过程

总结:在系统调用结束返回(iret)之前,可能再次进行系统调度(call_schedule),调度过程中还可能发生进程上下文与中断上下文之间的切换。系统完成这一次调用后,会继续检查任务队列,之后才执行iret返回。

陈政/arc001    原创作品转载请注明出处  《Linux内核分析》MOOC课程

转载于:https://my.oschina.net/bgbfbsdchenzheng/blog/647887

  • 点赞
  • 收藏
  • 分享

    • 文章举报

分析system_call中断处理过程 分析system_call中断处理过程
weixin_34278190
发布了160 篇原创文章 · 获赞 62 · 访问量 18万+

私信 关注

原文始发于:分析system_call中断处理过程

主题测试文章,只做测试使用。发布者:sys234,转转请注明出处:http://www.cxybcw.com/70660.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code