分析write中断处理过程
由于新浪微博不能很好地表现代码,我转战博客园~不过依旧是先留名:
李洋 创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
这一次实验的任务是使用gdb跟踪分析一个系统调用内核函数,我选择的是4号中断:write
write 的函数原型为 1 Int write(int filedesc, char* buffer, int size);
具体地在上一次实验中解释过了http://blog.sina.com.cn/s/blog_c50d17420102vdyj.html,这里不再赘述。
首先是改写实验代码,也就是增加我要调用的系统调用进MENU:
然后编译运行,makefile~一切OK:
然后就是这次的重头戏了,gdb跟踪内核是如何切换到内核态并执行内核服务程序~然后再切换回来的。
调试的主要步骤在孟老师的视频教学里有,我就不再重复了,简单发个图:
关于老师所说的无法跟踪调试system_call,因为是一段汇编代码,我觉着汇编代码是可以跟踪调试的,只是入口找的不准确,所以发生了一些意外(至于是什么我也没有跟踪到,似乎是一些宏定义的和地址的转化),我采用了一种替代的方案来进行调试,能跟踪大部分的执行过程。
这是我的解决方案:首先我使用 1 display /i $pc
来显示汇编指令,然后 b arch/x86/kernel/entry32.S:424
这里424是行号,也可以换为:sysenter_do_call。。。应该还有更早的,比如sysenter_audit,不过执行过程让我很疑惑。。。。。。我还没有找到最早执行的代码,我姑且是先从这里开始分析得。 ni 来逐行跟踪汇编代码,也可以用si,就可一直跟踪到iret了。
内核中主要实现系统调用的代码可以点击链接查看:http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/kernel/entry_32.S#sysenter_do_call
下面我来演示一下追踪得过程:
这是进入调用,然后参照代码,会参照一个系统调用表sys_call_table来调度具体的函数:
然后如图,sys_write执行完毕后,会调用sysenter_afer_call来开始返回用户态的工作:
这里先后执行了sysexit_audit,syscall_exit_work,work_pending,restore_all_notrace,restore_nocheck最后到irq_return。
这之前应该还有一个SAVEALL和syscall_trace_entry的过程,只是我还没有找到确切入口,我会再尝试一下。
总结一下这个过程就是:
时间所限,以上还不能很好地概括具体地过程,因为是汇编代码,不是很好用模块的方式表达,所以最还的方式还是具体地一步一步追踪调试一下。
简而言之,中断服务就是操作系统保存用户现场(寄存器,堆栈状态blablabla)切换到内核执行内核代码,进行中断服务然后恢复现场的过程。