1. 程式人生 > >使用gdb跟蹤分析一個系統呼叫核心函式

使用gdb跟蹤分析一個系統呼叫核心函式

“郭孟琦 + 原創作品轉載請註明出處 + 《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 ”

繼續上週的內容,首先利用gdb跟蹤系統呼叫system_call的處理過程。

這裡我繼續使用上週編寫的uname。

首先是為menuOS 新增uname的命令,這一過程很簡單直接在test.c中新增函式呼叫,並將uname和uname-asm函式的程式碼貼上過來就可以了。

下一步就開始正式跟蹤一個系統呼叫

開啟qemu並使用gdb。

在文件中找到uname在系統呼叫中的函式——sys_newuname

執行uname命令時停住了

break的位置

在後續中除錯找到了 在系統呼叫中還會檢查任務是否需要排程

但總體上我認為這次除錯是失敗的,搞了將近一天gdb總是進入Cannot find bounds of current function這個狀態。實在是沒法繼續下去了

在閱讀原始碼(/linux-3.18.6/arch/x86/kernel/entry_32.S)後我認為system_call開始到iret結束之間的整個過程大致如下(一些巨集定義的條件內容我略過了)

對於具體的中斷返回時排程的機制,這裡引用了一篇文章http://blog.csdn.net/zhaqiwen/article/details/7793071(原文出處及作者沒有找到)

這一幅圖應該更好的解釋了從syscall_exit到返回使用者態這一過程


總結:

系統呼叫的過程涉及使用者態和核心態,而從使用者態進入核心態的鑰匙就是int 0x80這個軟中斷。在使用者態和核心態間由eax等暫存器負責儲存中斷服務程式的入口(中斷向量)和傳入引數,進入sys_call後會立即將eax以及其他暫存器儲存,並會根據eax內容執行具體的中斷服務程式。返回後由於中斷服務程式會改變系統訊號量等內容,所以要處理更新訊號,並進行程序排程,這裡應該是程序切換的時機之一,當一切結束後執行恢復現場,這一次的系統呼叫也就結束了。

而執行syscall_exit_work的關鍵就在於testw $_TIF_ALLWORK_MASK, %cx

也就是檢查是否還有其它工作要完成。


對於一般的中斷,我認為處理機制與系統呼叫區別不大如儲存、恢復現場、程序排程,但是由於外部中斷不可提前預知,因此不會用如eax來提前存入中斷服務程式的入口,而是硬體會根據中斷源直接進入不同的中斷服務程式。感覺有點像把eax和table這部分做成硬體實現而不是軟體實現了。