前言
先占个位置,在实验楼做实验,刚做完一半忘了延续时间,结果之前写的代码神马的全没了。让我先去角落哭会,总结明天再写。2015-04-04 今天继续昨天未完工的内容,跟踪到一半发现运行结果有些奇怪,一直s了一段时间后坚持不下去了,finish了一下发现跟踪中出现问题了,最后也不知跟踪到了哪里,算了,还是直接寻找分析system_call中断处理过程吧。2015-04-05 之前代码参考地址:《Linux内核分析》之触发一个系统调用实验总结
代码与分析
跟踪截图
多图预警,由于跟踪失败,感觉仅可做个动过手的见证,但可看性不高,可以略过,具体的看个人了。明天添加干货。2015-04-05 [toggle hide=“yes” title=“跟踪截图” color=""]
从下图开始出现各种神奇的代码
最后finish的两张图
[/toggle]
主要代码段
xref: /linux-3.18.6/arch/x86/kernel/entry_32.S的490行起(持续更新中-2014-4-7)
# system call handler stubENTRY(system_call) RING0_INT_FRAME # can't unwind into user space anyway ASM_CLAC pushl_cfi %eax # save orig_eax SAVE_ALL GET_THREAD_INFO(%ebp) # system call tracing in operation / emulation testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp) jnz syscall_trace_entry cmpl $(NR_syscalls), %eax jae syscall_badsyssyscall_call: call *sys_call_table(,%eax,4)syscall_after_call: movl %eax,PT_EAX(%esp) # store the return valuesyscall_exit: LOCKDEP_SYS_EXIT DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx testl $_TIF_ALLWORK_MASK, %ecx # current->work jne syscall_exit_work代码分析
SYSCALL_VECTOR系统调用的终端向量,system_call汇编代码的入口 当执行int0x80的指令立即跳转到system_call这个位置,其位置在xref: /linux-3.18.6/arch/x86/kernel/entry_32.S的ENTRY(system_call) SAVE_ALL保护现场 call *sys_call_table(,%eax,4) %eax传递系统调用号,此段在本实验中实际执行的是sys_fork() movl %eax,PT_EAX(%esp) 调用完之后保存返回值。 退出之前若无syscall_exit_work则restore_all<返回用户态>返回用户态> 反之:进入syscall_exit_work,里面有个进程调度时机。
简略伪代码
部分分析在代码中注释。
ENTRY(system_call) SAVE_ALLsyscall_call: call *sys_call_table(,%eax,4) movl %eax,PT_EAX(%esp) # store the return valuesyscall_exit: testl $_TIF_ALLWORK_MASK, %ecx # current->work //检测当前的任务是否需要处理syscall_exit_work jne syscall_exit_workrestore_all: TRACE_IRQS_IRETirq_return: INTERRUPT_RETURN //不需时执行restore_all和irq_return结束ENDPROC(system_call) //一般需要处理一些,若当前系统接收到一些信号如需要调度时,执行syscall_exit_worksyscall_exit_work: testl $_TIF_WORK_SYSCALL_EXIT, %ecx jz work_pending //跳转到work_pendingEND(syscall_exit_work)work_pending: testb $_TIF_NEED_RESCHED, %cl jz work_notifysig //处理信号work_resched: //重新调度 call schedule jz restore_all //调度完成跳转至restore_all(将恢复现场的工作结束掉)返回系统调用work_notifysig: 。。。END(work_pending)在系统调用返回之前可能发生进程调度(即call schedule),当前进程可能有些信号需要处理(即work_notifysig) 小白分析,代码及下面的流程图错误难免,欢迎及时指出。 
总结
当一个系统调用发生时,进入内核处理系统调用,内核提供了一些服务,服务结束返回用户态之前可能会发生进程调度,进程调度里面会发生中断上下文的切换和进程上下文的切换。 内核可以抽象成是很多种不同的中断处理过程的集合,一些内核线程可当成一般的服务理解。 windCoder原创作品转载请注明出处
参考资料
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
评论