系统调用处理过程

使用gdb跟踪系统调用内核函数sys_time

查看  linux-3.18.6/arch/x86/syscalls/syscall_32.tbl

13	i386	time			sys_time			compat_sys_time

可以得知,13号系统调用time对应的内核处理函数是sys_time

1. 设置断点 b sys_time

系统调用处理过程_第1张图片
设置断点 b sys_time

2. 设置断点 b system_call

系统调用处理过程_第2张图片
设置断点 b system_call

可以看到,在system_call的地方,并没有停下,因为system_call不是一个正常的函数,它是一段汇编代码,怎么让系统停在system_call的位置进行调试?

查看  linux-3.18.6/arch/x86/kernel/entry_32.S

系统调用处理过程_第3张图片
查看ENTRY(system_call)

gdb应该可以发现system_call它声明了一个函数原型,但它实际上不是一个函数,而只是一段汇编代码的起点


系统调用的机制的初始化

\init\main.c
      start_kernel
\arch\x86\kernel\traps.c
      #ifdef CONFIG_X86_32
            set_system_trap_gate(SYSCALL_VECTOR, &system_call);
            set_bit(SYSCALL_VECTOR, used_vectors);
      #endif

系统调用的工作机制一旦在start_kernel()初始化好之后,在代码中一旦出现int 0x80的指令,它就会立即跳转到system_call这个位置

490ENTRY(system_call)

这个位置是执行完int 0x80这条指令的下一条指令

490ENTRY(system_call)			# system_call的位置
491	RING0_INT_FRAME			# can't unwind into user space anyway
492	ASM_CLAC
493	pushl_cfi %eax			# save orig_eax
494	SAVE_ALL			# 保护现场
495	GET_THREAD_INFO(%ebp)
496					# system call tracing in operation / emulation
497	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
498	jnz syscall_trace_entry
499	cmpl $(NR_syscalls), %eax
500	jae syscall_badsys
501syscall_call:
502	call *sys_call_table(,%eax,4)	# 系统调用表,eax存放系统调用号,相当于调用sys_time
503syscall_after_call:
504	movl %eax,PT_EAX(%esp)		# store the return value  保存返回值
505syscall_exit:
506	LOCKDEP_SYS_EXIT
507	DISABLE_INTERRUPTS(CLBR_ANY)	# make sure we don't miss an interrupt
508					# setting need_resched or sigpending
509					# between sampling and the iret
510	TRACE_IRQS_OFF
511	movl TI_flags(%ebp), %ecx
512	testl $_TIF_ALLWORK_MASK, %ecx	# current->work
513	jne syscall_exit_work		# 一旦进入到syscall_exit_work里面,会有进程调度时机
514
515restore_all:
516	TRACE_IRQS_IRET
517restore_all_notrace:			# 返回到用户态
518#ifdef CONFIG_X86_ESPFIX32
519	movl PT_EFLAGS(%esp), %eax	# mix EFLAGS, SS and CS
520	# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
521	# are returning to the kernel.
522	# See comments in process.c:copy_thread() for details.
523	movb PT_OLDSS(%esp), %ah
524	movb PT_CS(%esp), %al
525	andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
526	cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
527	CFI_REMEMBER_STATE
528	je ldt_ss			# returning to user-space with LDT SS
529#endif
530restore_nocheck:
531	RESTORE_REGS 4			# skip orig_eax/error_code
532irq_return:
533	INTERRUPT_RETURN		# 这个地方就是iret,系统调用的处理过程到此结束


系统调用处理过程的汇编伪代码

系统调用处理过程_第4张图片
系统调用处理过程的汇编伪代码

当一个系统调用发生的时候,它进入内核处理系统调用,内核提供了一些服务,在这个服务结束返回到用户态之前,可能会发生进程调度,在进程调度里面,就会发生进程上下文的切换

可以把内核抽象成很多中不同的中断处理过程的集合


(完)

你可能感兴趣的:(系统调用处理过程)