系统调用

       有些工作如果只是在用户空间是没有办法完成的,比如取得时间、操作文件等,这个时候就需要系统调用了。而一般的系统调用的过程是:我们的程序调用C库包装好的一些函数,这些函数去执行系统调用,然后再把返回的结果给我们看。现在有一个问题就出现了:用户空间是不能去访问内存空间的,那么怎么去运行内核空间中的代码呢?具体的过程如下:

       首先程序触发int 0x80中断陷入内核态。

       然后系统跳到一个预设的内核地址,该位置指向了系统调用处理程序system_call,下面是该函数的代码:

ENTRY(system_call)
	RING0_INT_FRAME
	pushl %eax
	CFI_ADJUST_CFA_OFFSET 4
	SAVE_ALL
#ifdef CONFIG_EVENT_TRACE
	pushl %edx; pushl %ecx; pushl %ebx; pushl %eax
	call sys_call
	popl %eax; popl %ebx; popl %ecx; popl %edx
#endif
	GET_THREAD_INFO(%ebp)
	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
	jnz syscall_trace_entry
	cmpl $(nr_syscalls), %eax
	jae syscall_badsys
syscall_call:
	call *sys_call_table(,%eax,4)
	movl %eax,PT_EAX(%esp)
syscall_exit:
	LOCKDEP_SYS_EXIT
	DISABLE_INTERRUPTS(CLBR_ANY)
	TRACE_IRQS_OFF
	testl $TF_MASK,PT_EFLAGS(%esp)
	jz no_singlestep
	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
no_singlestep:
	movl TI_flags(%ebp), %ecx
	testw $_TIF_ALLWORK_MASK, %cx
	jne syscall_exit_work
restore_all:
	movl PT_EFLAGS(%esp), %eax
	movb PT_OLDSS(%esp), %ah
	movb PT_CS(%esp), %al
	andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
	cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
	CFI_REMEMBER_STATE
	je ldt_ss
restore_nocheck:
	TRACE_IRQS_IRET
restore_nocheck_notrace:
	RESTORE_REGS
	addl $4, %esp
	CFI_ADJUST_CFA_OFFSET -4
irq_return:
	INTERRUPT_RETURN
.section .fixup,"ax"
iret_exc:
	pushl $0
	pushl $do_iret_error
	jmp error_code
.previous
.section __ex_table,"a"
	.align 4
	.long irq_return,iret_exc
.previous
	CFI_RESTORE_STATE
ldt_ss:
	larl PT_OLDSS(%esp), %eax
	jnz restore_nocheck
	testl $0x00400000, %eax
	jnz restore_nocheck
#ifdef CONFIG_PARAVIRT
	cmpl $0, pv_info+PARAVIRT_enabled
	jne restore_nocheck
#endif
	movl PT_OLDESP(%esp), %eax
	movl %esp, %edx
	call patch_espfix_desc
	pushl $__ESPFIX_SS
	CFI_ADJUST_CFA_OFFSET 4
	pushl %eax
	CFI_ADJUST_CFA_OFFSET 4
	DISABLE_INTERRUPTS(CLBR_EAX)
	TRACE_IRQS_OFF
	lss (%esp), %esp
	CFI_ADJUST_CFA_OFFSET -8
	jmp restore_nocheck
	CFI_ENDPROC
ENDPROC(system_call)
其中通过call *sys_call_table(,%eax,4)来调用相应编号的系统调用,参数可以通过ebx、ecx、edx、esi来传送。而sys_call_table的定义如下:
ENTRY(sys_call_table)
	.long sys_restart_syscall
	.long sys_exit
	.long sys_fork
	.long sys_read
	.long sys_write
	.long sys_open
	.long sys_close
	.long sys_waitpid
	.long sys_creat
	// ...
系统调用的服务例程都背定义为asmlinkage,表示只从堆栈中获取该函数的参数。








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值