定義
每個(gè)進(jìn)程都有用戶堆棧和內(nèi)核堆棧兩個(gè)堆棧。進(jìn)程在用戶態(tài)時(shí)使用用戶堆棧,陷入到內(nèi)核態(tài)時(shí)便使用內(nèi)核堆棧。
切換過程
- 用戶進(jìn)程X正常運(yùn)行時(shí),堆棧寄存器ESP指向的的用戶堆棧地址。
- 當(dāng)進(jìn)程X調(diào)用某系統(tǒng)調(diào)用時(shí)(int 0x80),CPU會(huì)首先將用戶堆棧地址保存到內(nèi)核堆棧內(nèi)(還有EIP,F(xiàn)LAG等寄存器),然后將ESP指針指向內(nèi)核堆棧地址(還有將內(nèi)態(tài)的EIP,F(xiàn)LAG等也一并存入相應(yīng)的寄存器中,切換到用戶態(tài)進(jìn)程),這時(shí)便切換到來內(nèi)核堆棧中。
- 當(dāng)系統(tǒng)調(diào)用完成后,再將用戶堆棧地址從內(nèi)核堆棧中出棧存儲(chǔ)ESP寄存器中,此時(shí)便切換到了用戶堆棧。
中斷過程
- X函數(shù)調(diào)用syscall_x (用戶態(tài))
- int 0x80 (保存部分寄存器,內(nèi)核態(tài))
- syscall_call (SAVE_ALL保存全部現(xiàn)場(chǎng),內(nèi)核態(tài))
- iret后(用戶態(tài))
中斷代碼(簡(jiǎn)易)
ENTRY(system_call)
RING0_INT_FRAME
ASM_CLAC
push_cfi %eax #保存系統(tǒng)調(diào)用號(hào)
SAVE_ALL #保存現(xiàn)場(chǎng)??
GET_THREAD_INFO(%ebp)
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%epb)
jnz syscall_trace_entry
cmpl $(nr_syscalls), %eax #檢查傳入到系統(tǒng)調(diào)用號(hào)是否合法
jae syscall_badsys
syscall_call:
call *sys_call_table(,%eas,4) #執(zhí)行相應(yīng)的系統(tǒng)調(diào)用函數(shù)
movl %eax,PT_EAX(%ebp) #保存結(jié)果到eax寄存器
syscall_exit:
testl $_TIF_ALLWORK_MASK,%ecx #檢查是否有其他任務(wù)處理
jne syscall_exit_work #進(jìn)行進(jìn)程調(diào)度
restore_all
TRACE_IRQS_IRET #恢復(fù)現(xiàn)場(chǎng)
irq_return:
INTERRUPT_RETURN #iret 將ESP,EIP,F(xiàn)LAG等寄存器恢復(fù)為用戶態(tài)