聂新桥 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程
在内核源码的start_kernel函数里,调用的初始化中断的trap_init()
trap_init()会设定硬件中断相应的处理代码和系统调用处理代码
(, &);
SYSCALL_VECTOR = 0x80 system_call是汇编起点地址。
在arch/x86/kernel/entry_32.S里可以找到符号system_call
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
要知道系统调用与中断都被cpu当成异常,硬件会自动保存用户态的ss,esp, eflags 和cs eip在内核态的堆栈上。
然后的SAVE_ALL宏会保存其他的寄存器。最后的几句汇编修改了段寄存器fs,gs,es不知道是怎么意思。
.macro SAVE_ALL
cld
PUSH_GS
pushl_cfi %fs
/*CFI_REL_OFFSET fs, 0;*/
pushl_cfi %es
/*CFI_REL_OFFSET es, 0;*/
pushl_cfi %ds
/*CFI_REL_OFFSET ds, 0;*/
pushl_cfi %eax
CFI_REL_OFFSET eax, 0
pushl_cfi %ebp
CFI_REL_OFFSET ebp, 0
pushl_cfi %edi
CFI_REL_OFFSET edi, 0
pushl_cfi %esi
CFI_REL_OFFSET esi, 0
pushl_cfi %edx
CFI_REL_OFFSET edx, 0
pushl_cfi %ecx
CFI_REL_OFFSET ecx, 0
pushl_cfi %ebx
CFI_REL_OFFSET ebx, 0
movl $(__USER_DS), %edx
movl %edx, %ds
movl %edx, %es
movl $(__KERNEL_PERCPU), %edx
movl %edx, %fs
SET_KERNEL_GS %edx
.endm
最后用户态进程的整个状态被完整的记录到内核的栈上了。他的状态映像如下:
* 0(%esp) - %ebx
* 4(%esp) - %ecx
* 8(%esp) - %edx
* C(%esp) - %esi
* 10(%esp) - %edi
* 14(%esp) - %ebp
* 18(%esp) - %eax
* 1C(%esp) - %ds
* 20(%esp) - %es
* 24(%esp) - %fs
* 28(%esp) - %gs saved iff !CONFIG_X86_32_LAZY_GS
* 2C(%esp) - orig_eax
* 30(%esp) - %eip
* 34(%esp) - %cs
* 38(%esp) - %eflags
* 3C(%esp) - %oldesp
* 40(%esp) - %oldss
内核此刻可以处理用户进程的请求了,首先是判断用户要调用的是合法的系统调用,超过最大系统调用NR_syscall就不合法了。
接着call *sys_call_table(,%eax,4)这个相当于查找系统调用的地址,sys_call_table相当于一系列系统调用的函数指针数组的首地址。
也就是调用sys_call_table+4*eax地址保存的函数指针指向的函数。
cmpl $(NR_syscalls), %eax
jae syscall_badsys
syscall_call:
call *sys_call_table(,%eax,4)
以getppid为例,他应该调用sys_getppid,可是居然源码里面找不到sys_getppid在哪里,用gdb试一下
可以看出符号表在kernel/sys.c里面
()
{
int ;
rcu_read_lock();
= (rcu_dereference(current->));
rcu_read_unlock();
return ; }
又是宏定义。
处理完系统调用相关的函数后,这个进程不一定会立即恢复执行,内核会处理进程收到的信号,并进行调度。
处理完这些以后内核态iret进入用户态。执行用户进程。
大致的处理过程就是这个样子。具体的细节实在太复杂,还得继续努力。
阅读(2239) | 评论(2) | 转发(0) |