使用gdb跟踪分析一个系统调用内核函数

来源:互联网 发布:收费视频源码 编辑:程序博客网 时间:2024/05/06 20:57

“郭孟琦 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”


继续上周的内容,首先利用gdb跟踪系统调用system_call的处理过程。

这里我继续使用上周编写的uname。


首先是为menuOS 添加uname的命令,这一过程很简单直接在test.c中添加函数调用,并将uname和uname-asm函数的代码粘贴过来就可以了。


下一步就开始正式跟踪一个系统调用

开启qemu并使用gdb。

在文档中找到uname在系统调用中的函数——sys_newuname

执行uname命令时停住了

break的位置

在后续中调试找到了 在系统调用中还会检查任务是否需要调度

但总体上我认为这次调试是失败的,搞了将近一天gdb总是进入Cannot find bounds of current function这个状态。实在是没法继续下去了

在阅读源码(/linux-3.18.6/arch/x86/kernel/entry_32.S)后我认为system_call开始到iret结束之间的整个过程大致如下(一些宏定义的条件内容我略过了)

对于具体的中断返回时调度的机制,这里引用了一篇文章http://blog.csdn.net/zhaqiwen/article/details/7793071(原文出处及作者没有找到)

这一幅图应该更好的解释了从syscall_exit到返回用户态这一过程



总结:

系统调用的过程涉及用户态和内核态,而从用户态进入内核态的钥匙就是int 0x80这个软中断。在用户态和内核态间由eax等寄存器负责存储中断服务程序的入口(中断向量)和传入参数,进入sys_call后会立即将eax以及其他寄存器保存,并会根据eax内容执行具体的中断服务程序。返回后由于中断服务程序会改变系统信号量等内容,所以要处理更新信号,并进行进程调度,这里应该是进程切换的时机之一,当一切结束后执行恢复现场,这一次的系统调用也就结束了。


而执行syscall_exit_work的关键就在于testw $_TIF_ALLWORK_MASK, %cx也就是检查是否还有其它工作要完成。


对于一般的中断,我认为处理机制与系统调用区别不大如保存、恢复现场、进程调度,但是由于外部中断不可提前预知,因此不会用如eax来提前存入中断服务程序的入口,而是硬件会根据中断源直接进入不同的中断服务程序。感觉有点像把eax和table这部分做成硬件实现而不是软件实现了。

0 0
原创粉丝点击