接下來:call
do_syscall_64,進入do_syscall_64函數:
__visible void do_syscall_64(struct pt_regs *regs)
{
struct thread_info *ti = current_thread_info();
unsigned long nr = regs- >orig_ax;
enter_from_user_mode();
local_irq_enable();
if (READ_ONCE(ti- >flags) & _TIF_WORK_SYSCALL_ENTRY)
nr = syscall_trace_enter(regs);
/*
* NB: Native and x32 syscalls are dispatched from the same
* table. The only functional difference is the x32 bit in
* regs- >orig_ax, which changes the behavior of some syscalls.
*/
if (likely((nr & __SYSCALL_MASK) < NR_syscalls)) {
regs- >ax = sys_call_table[nr & __SYSCALL_MASK](
regs- >di, regs- >si, regs- >dx,
regs- >r10, regs- >r8, regs- >r9);
}
syscall_return_slowpath(regs);
}
上述函數的主邏輯很簡單:
1、 通過之前保存下來的pt_regs(往內核棧中格式化壓入的),獲取用戶傳入的系統(tǒng)調用號nr,系統(tǒng)調用號保存在了regs->orig_ax:
unsigned long nr = regs- >orig_ax;
2、 通過系統(tǒng)調用號nr,執(zhí)行對應的回調函數,sys_call_table是函數指針數組,不同nr對應不同系統(tǒng)調用對應的函數。其中regx->di、regx->si、regs->dx、regs->r10、regs->r8、regs->r9分別是之前保存到內核棧(以struct
pt_regs格式化)保存到pt_regs中的,對應著用戶傳入該系統(tǒng)調用的參數1~6:
if (likely((nr & __SYSCALL_MASK) < NR_syscalls)) {
regs- >ax = sys_call_table[nr & __SYSCALL_MASK](
regs- >di, regs- >si, regs- >dx,
regs- >r10, regs- >r8, regs- >r9);
}
以上就完成了用戶調用系統(tǒng)調用,并從用戶棧切換到內核棧,并執(zhí)行到系統(tǒng)調用號對應函數的過程。 具體的系統(tǒng)調用相關細節(jié)將在以后系統(tǒng)調用相關文章中分析。
系統(tǒng)調用-分析從內核棧切換用戶棧
上面分析到了執(zhí)行系統(tǒng)調用對應的函數,如下所示,并將返回值保存在regs->ax中了
regs- >ax = sys_call_table[nr & __SYSCALL_MASK](
regs- >di, regs- >si, regs- >dx,
regs- >r10, regs- >r8, regs- >r9);
函數執(zhí)行到do_syscall_64->syscall_return_slowpath(regs),開始為返回用戶態(tài)做準備.
并最終回到系統(tǒng)調用 內核SYSCALL 入口:ENTRY(entry_SYSCALL_64)->return_from_SYSCALL_64,繼續(xù)完成系統(tǒng)調用返回工作,并切換用戶棧與內核棧,使用struct pt_regs恢復用戶態(tài)寄存器值。
總之
用戶棧——>內核棧: cpu保存用戶當前堆棧信息保存到內核的棧中(恢復時用到),然后將cpu指向內核堆棧,去執(zhí)行內核代碼。完成用用戶棧到內核棧轉換。
內核棧——>用戶棧: 再切換到內核堆棧前,將用戶堆棧信息壓入到內核棧中,內核函數執(zhí)行完回退棧幀,會將用戶的堆棧信息POP出棧,然后cpu堆棧寄存器就知道怎么回去了,返回的用戶程序中斷的地方繼續(xù)執(zhí)行。
-
內核
+關注
關注
3文章
1410瀏覽量
41150 -
Linux
+關注
關注
87文章
11469瀏覽量
212913
發(fā)布評論請先 登錄
從 Linux 內核的角度談線程棧和進程棧

C函數調用機制與棧幀原理詳解

操作系統(tǒng)為什么分內核態(tài)和用戶態(tài)?這兩者如何切換?
用一個實例展示一下Linux內核棧幀的入棧和退棧過程
對Linux的進程內核棧的認識

帶你了解嵌入式C語言函數調用棧

鴻蒙內核源碼分析:用戶棧和內核棧的兩次切換

嵌入式系統(tǒng)中棧的變化

Linux中的進程棧、線程棧、內核棧以及中斷棧

linux中的進程棧,線程棧,內核棧的區(qū)別

評論