Linux笔记 · · By/蜜汁炒酸奶

《Linux内核分析》之分析system_call中断处理过程实验总结

前言

先占个位置,在实验楼做实验,刚做完一半忘了延续时间,结果之前写的代码神马的全没了。让我先去角落哭会,总结明天再写。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 stub
ENTRY(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_badsys
syscall_call:
	call *sys_call_table(,%eax,4)
syscall_after_call:
	movl %eax,PT_EAX(%esp)		# store the return value
syscall_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汇编代码的入口 当执行int$0x80时CPU自动跳转到system_call这个位置来执行 系统调用机制一旦在start_kernel初始化好之后,即在代码中一旦出现int$0x80的指令立即跳转到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_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 //检测当前的任务是否需要处理syscall_exit_work
	jne syscall_exit_work
restore_all:
	TRACE_IRQS_IRET
irq_return:
	INTERRUPT_RETURN  //不需时执行restore_all和irq_return结束
ENDPROC(system_call)
	//一般需要处理一些,若当前系统接收到一些信号如需要调度时,执行syscall_exit_work
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 //调度完成跳转至restore_all(将恢复现场的工作结束掉)返回系统调用
work_notifysig:
	。。。
END(work_pending)
在系统调用返回之前可能发生进程调度(即call schedule),当前进程可能有些信号需要处理(即work_notifysig) 小白分析,代码及下面的流程图错误难免,欢迎及时指出。

总结

当一个系统调用发生时,进入内核处理系统调用,内核提供了一些服务,服务结束返回用户态之前可能会发生进程调度,进程调度里面会发生中断上下文的切换和进程上下文的切换。 内核可以抽象成是很多种不同的中断处理过程的集合,一些内核线程可当成一般的服务理解。 windCoder原创作品转载请注明出处

 参考资料

Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

评论已关闭

example
C
蜜汁炒酸奶

当前处于试运行期间,可能存在不稳定情况,敬请见谅。

欢迎点击此处反馈访问过程中出现的问题