中断/int指令会在堆栈上保存一些寄存器的值
用户态栈顶地址、当时的状态字、当时的CS:eip的值
中断服务程序
进入中断服务程序首先SAVE_ALL(保护现场)
退出中断服务程序RESTROE_ALL(恢复现场)
中断处理的完整过程
Interrupt(ex:int 0x80)--Save cs:eip/ss:esp/eflags(curret)to kernel stack, then load cs:eip (entry of a specific ISR)and ss:esp(point to kernel stack),
SAVE_ALL
内核代码,完成中断服务,发生进程调度。
RESTORE_ALL
Iret-pop cs:eip/ss:esp/eflags from kernel stack
Libc库函数API与系统调用的关系
API只是一个函数定义
系统调用通过软中断向内核发出一个明确的请求
一个API可能会调用好几个系统调用
不同的API可能调用同一个系统调用
系统调用三层皮:xyz、system_call 和 sys_xyz
trap_init();
\arch\x86\kernel\traps.c
#ifdef CONFIG_X86_32
Set_system_trap_gate(SYSCALL_VECTOR, &system_call);
Set_bit(SYSCALL_VECTOR, used_vectors);
#endif
遇到Int 0x80指令
跳转到system_call位置
需要仔细分析的是,系统调用的处理过程(即,system_call的处理过程):
ENTRY(system_call)
SAVE_ALL
Syscall_call:
Call *sys_call_table(,%eax,4)
Movl %eax,PT_EAX(%esp) # store the return value
Syscall_exit:
Testl $_TIF_ALLWORK_MASK,%ecx #current->work
Jne syscall_exit_work
Restore_all:
RESTORE_INT_REGS
Irq_return:
INTERRUPT_RETURN
ENDPROC(system_call)
Sycall_exit_work:
Testl $_TIF_WORK_SYSCALL_EXIT, %ecx
Jz work_pending
END(syscall_exit_work)
Work_pending:
Testb $_TIF_NEED_RESCHED, %cl
Jz work_notifysig
work_resched:
Call schedule #进程调度
Jz restore_all
Work_notifysig: #deal with pending signals
...
END(work_pending)
系统调用返回之前有可能发生进程调度
系统调用返回之前有可能会去处理信号