5.分析system_call中断处理过程

来源:互联网 发布:转换淘宝网址分享微信 编辑:程序博客网 时间:2024/06/15 18:49

请注意:>原作者:张澍> 原创作品转载请注明出处> 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

  • 实验步骤
    • 1 GDB代码中调试menu_os
    • 2 Linux源码中跟踪
  • 总结

1.实验步骤

1.1 GDB代码中调试menu_os

Linux中编辑运行:

$ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S #运行menu_os$gdb                               #启动GDB(gdb) file linux-3.18.6/vmlinux     #加载内核(gdb) target remote :1234           #链接到menu_os(gdb) b start_kernel                #在start_kernel处设置断点(gdb) c                             #运行到断点:start_kernel处(gdb) list                          #查看此处代码 (gdb) b sys_time                    #在start_kernel处设置断点(gdb) c(gdb) s                             #但步执行(gdb) finish                        #执行完此函数“get_seconds()”#注意:sys_time返回后进入汇编代码处理GDB无法继续跟踪(gdb) b system_call(gdb) c                             #此时menu_os界面显示time命令返回

运行显示

这里写图片描述

犹豫sys_time返回后进入汇编代码处理GDB无法继续跟踪,故接下来在Linux源码中直接查看

1.2 Linux源码中跟踪

#文件位置:linux-3.18.6/init/main.c    start_kernel() -> trap_init() ->#文件位置:linux-3.18.6/arch/x86/kernel/traps.c    trap_init() ->    #ifdefCONFIG_X86_32    set_system_trap_gate(SYSCALL_VECTOR, &system_call);     set_bit(SYSCALL_VECTOR, used_vectors);     #endif    $0x80 -> system_call -> #文件位置:linux-3.18.6/arch/x86/kernel/entry_32.S    ENTRY(system_call)  #系统调用终端处理函数        SAVE_ALL  //保存现场        syscall_call:            *sys_call_table(,%eax,4)  #根据系统调用号调用相应的系统内核函数        syscall_exit:            testl $_TIF_ALLWORK_MASK, %ecx   #检查当前的任务是否需要处理syscall_exit_work (如传入某信号)            jne syscall_exit_work        #如果不需要处理        restore_all:            TRACE_IRQS_IRET        irq_return:            INTERRUPT_RETURN  #系统调用处理结束        #如果需要处理        syscall_exit_work:            testl $_TIF_WORK_SYSCALL_EXIT, %ecx            jz work_pending  #跳转到 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:            ...        #处理信号        END(work_pending)  #返回系统调用    ENDPROC(system_call)

2.总结

系统调用处理过程:

  1. 用户态调用系统API,触发“int 0x80中断”
  2. 内核收到“int 0x80中断”后进入内核态
  3. 内核态中根据系统调用号调用相应的系统内核函数
  4. 进行相应的进程调度与信号处理
  5. 返回系统调用重新回到用户态
0 0