您的位置:首页 > 其它

系统调用system_call的处理过程

2016-03-27 12:19 435 查看
本周分析linux源码中系统调用system_call的处理过程

syttem_call位于/linux-3.18.6/arch/x86/kernel/entry_32.S中,源码如下:

<pre name="code" class="plain">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)    #根据系统调用表查找相应的系统调用函数,比如我们调用
gitpid(),其对于系统调用函数好为20,系统调用号20通过eax传递过去
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           #系统调用过程中可能会发生进程调度,这个函数比较有意思,下面会贴出主要源码分析
restore_all:
TRACE_IRQS_IRET
restore_all_notrace:



syscall _exit_work主要源码如下,我们会详细分析下

work_pending:
testb $_TIF_NEED_RESCHED, %cl   #需要重新进程调度吗?
jz work_notifysig               #是,进行信号处理工作,其源码见下面
work_resched:
call schedule                   #调用调度器,进行进程的调度工作
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
andl $_TIF_WORK_MASK, %ecx	# is there any work to be done other
# than syscall tracing?
jz restore_all
testb $_TIF_NEED_RESCHED, %cl
jnz work_resched

work_notifysig:				# deal with pending signals and
# notify-resume requests
#ifdef CONFIG_VM86
testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
movl %esp, %eax
jne work_notifysig_v86		# returning to kernel-space or
# vm86-space
1:
#else
movl %esp, %eax
#endif
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
movb PT_CS(%esp), %bl
andb $SEGMENT_RPL_MASK, %bl
cmpb $USER_RPL, %bl
jb resume_kernel
xorl %edx, %edx
call do_notify_resume
jmp resume_userspace

#ifdef CONFIG_VM86
ALIGN
work_notifysig_v86:
pushl_cfi %ecx			# save ti_flags for do_notify_resume
call save_v86_state		# %eax contains pt_regs pointer
popl_cfi %ecx
movl %eax, %esp
jmp 1b
#endif
END(work_pending)

# perform syscall exit tracing
ALIGN
syscall_trace_entry:
movl $-ENOSYS,PT_EAX(%esp)
movl %esp, %eax
call syscall_trace_enter
/* What it returned is what we'll actually use.  */
cmpl $(NR_syscalls), %eax
jnae syscall_call
jmp syscall_exit
END(syscall_trace_entry)

# perform syscall exit tracing
ALIGN
syscall_exit_work:
testl $_TIF_WORK_SYSCALL_EXIT, %ecx
jz work_pending              #在syscall_exit_work过程中有可能会发生进程调度,见上面的work_pending分析
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_ANY)	# could let syscall_trace_leave() call
# schedule() instead
movl %esp, %eax
call syscall_trace_leave
jmp resume_userspace
END(syscall_exit_work)
小结:system_call进入内核进行系统调用,调用完毕退出的过程中会有进程调度的处理工作

“codeyangjun
+ 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: