linux系统调用函数少,陷入内核效率高,过程大概是这样的:
1,初始化阶段,登录门描述符的处理:
./arch/i386/kernel/traps.c
void __init trap_init(void)
{
...
set_system_gate(SYSCALL_VECTOR,&system_call);
...
}
2,程序中使用 int 0x80指令陷入内核,CPU切换到内核态,执行对应的处理函数,这里为system_call
./arch/i386/kernel/entry.S
...
ENTRY(system_call)
pushl %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
# system call tracing in operation
testb $(_TIF_SYSCALL_TRACE|_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,EAX(%esp) # store the return value
syscall_exit:
cli # make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx # current->work
jne syscall_exit_work
...
3,其中call *sys_call_table(,%eax,4)调用sys_XXX函数,完成系统调用功能。
系统调用号通过eax寄存器传递给内核,其他参数通过ebx,ecx等,内核通过SAVE_ALL将其保存在内核栈中,因为所有系统调用函数sys_XXX都是asmlinkage的,也就是从栈中取得参数。返回值保存在eax中
#define SAVE_ALL /
cld; /
pushl %es; /
pushl %ds; /
pushl %eax; /
pushl %ebp; /
pushl %edi; /
pushl %esi; /
pushl %edx; /
pushl %ecx; /
pushl %ebx; / //注意压栈的顺序,
movl $(__USER_DS), %edx; /
movl %edx, %ds; /
movl %edx, %es;
重点:用户态切换到内核态,栈切换,参数传递
参考:情景分析中断/系统调用章节