linux利用陷阱門來處理異常,利用中斷門來處理中斷。異常和中斷對應處理程式都屬於核心**段,所以,所有中斷門和陷阱門的段選擇符(0x60)都指向 gdt 中的「核心**段」描述符。
通過中斷門進入到乙個中斷服務程式時,cpu 會清除 eflags 暫存器中的 if 標誌,即關中斷;通過陷阱門進入乙個異常處理程式時,cpu 不會修改 if 標誌。也就是說,外部中斷不支援巢狀處理,而內部異常則支援巢狀處理。
任務門描述符中不包含偏移位址,只包含 tss 段選擇符,這個段選擇符指向 gdt 中的乙個 tss 段描述符,cpu 根據 tss 段中的相關資訊裝載ss 和 esp 等暫存器,從而執行相應的異常處理程式。
linux中,將型別號為8的雙重故障(#df)用任務門實現,而且是唯一通過任務門實現的異常。雙重故障 tss 段描述符在 gdt 中位於索引值為 0x1f 的表項處,即13位索引為0 0000 0001 1111,且其ti=0(指向 gdt),rpl=00(核心級**),即任務門描述符中的段選擇符為00f8h。
異常處理程式傳送相應的訊號給發生異常的當前程序,或者進行故障恢復,然後返回到斷點處執行。例如,若執行了非法操作,cpu就產生6號異常(#ud),在對應的異常處理程式中,向當前程序傳送乙個sigill訊號,以通知當前程序中止執行。
採用向發生異常的程序傳送訊號的機制實現異常處理,可盡快完成在核心態的異常處理過程,因為異常處理過程越長,巢狀執行異常的可能性越大,而異常巢狀執行會付出較大的代價。並不是所有異常處理都只是傳送乙個訊號到發生異常的程序。例如,對於14號頁故障異常(#pf),需要判斷是否訪問越級、越權或越界等,若發生了這些無法恢復的故障,則頁故障處理程式傳送sigse**訊號給發生頁故障異常的程序;若只是缺頁,則頁故障處理程式負責把所缺失頁面從磁碟裝入主存,然後返回到發生缺頁故障的指令繼續執行。
所有異常處理程式的結構是一致的,都可劃分成以下三個部分:
準備階段:在核心棧儲存通用暫存器內容(稱為現場資訊),這部分大多用組合語言程式實現。
處理階段:採用c函式進行具體處理。函式名由do_字首和處理程式名組成,如 do_overflow 為溢位處理函式。大部分函式的處理方式:儲存硬體出錯碼(如果有的話)和異常型別號,然後,向當前程序傳送乙個訊號。當前程序接受到訊號後,若有對應訊號處理程式,則轉訊號處理程式執行;若沒有,則呼叫核心abort例程執行,以終止當前程序。恢復階段:恢復儲存在核心棧中的各個暫存器的內容,切換到使用者態並返回到當前程序的斷點處繼續執行。
pic需對所有外設來的 irq請求按優先順序排隊,若至少有乙個irq線有請求且未被遮蔽,則 pic向 cpu的 intr引腳發中斷請求。
cpu每執行完一條指令都會查詢 intr,若發現有中斷請求,則進入中斷響應過程(關中斷、保護斷點和現場、發中斷查詢訊號),調出中斷服務程式執行。
所有中斷服務程式的結構類似,都劃分為以下三個階段。
準備階段:在核心棧中儲存各通用暫存器的內容(稱為現場資訊)以及所請求 irqi 的值等,並給pic回送應答資訊,允許其傳送新的中斷請求訊號。
處理階段:執行 irqi 對應的中斷服務例程 isr (interrupt server routine)。中斷型別號為32+i
恢復階段:恢復儲存在核心棧中的各個暫存器的內容,切換到使用者態並返回到當前程序的邏輯控制流的斷點處繼續執行。
系統呼叫(陷阱)是特殊異常事件,是os為使用者程式提供服務的手段linux提供了幾百種系統呼叫,主要分為以下幾類:程序控制,檔案操作,檔案系統操作,系統控制,記憶體管理,網路管理,使用者管理,程序通訊等
系統呼叫號是系統呼叫跳轉表索引值,跳轉表給出系統呼叫服務例程首位址。
linux系統中printf()函式的執行過程
軟中斷指令int $0x80的執行過程,它是陷阱類(程式設計異常)事件,因此它與異常響應過程一樣。
將idti(i=128)中段選擇符(0x60)所指gdt中的核心**段描述符取出, 其dpl=0,此時cpl=3(因為int $0x80指令在使用者程序中執行),因而cpl>dpl且idti 的 dpl=cpl,故未發生13號異常。讀 tr 暫存器,以訪問tss,從tss中將核心棧的段暫存器內容和棧指標裝入ss和esp;依次將執行完指令int $0x80時的ss、esp、eflags、cs、eip的內容(即斷點和程式狀態)儲存到核心棧中,即當前ss∶esp所指之處;
將idti(i=128)中段選擇符(0x60)裝入cs,偏移位址裝入eip。這裡,cs:eip即是系統呼叫處理程式system_call(所有系統呼叫的入口程式)第一條指令的邏輯位址
執行int $0x80需一連串的一致性和安全性檢查,因而速度較慢。從pentium ii開始,intel引入了指令sysenter和sy***it,分別用於從使用者態到核心態、從使用者態到核心態的快速切換。
以上總結,主要參考袁春風老師計算機系統系列課程。
異常和中斷處理
引導程式被讀到記憶體後,開始執行引導程式,以裝入作業系統核心,並對gdt,idt等進行初始化,系統啟動後,進入保護模式。每條指令執行過程中,cpu會根據執 況判定是否發生了某種內部異常事件,並在某條指令執行結束時判定是否發生了外部中斷請求 由此可見,異常事件和中斷請求的檢測都是在某一條指令執行過程中...
Linux中斷和中斷處理
眾所周知,處理器的速度跟外圍的硬體裝置的速度往往不在乙個數量級上,因此,如果核心採取讓處理器傳送乙個請求,然後專門等待回應的辦法,顯然差強人意。既然硬體處理的這麼慢,那麼核心就應該在這期間去處理其他事務,等待硬體真正完成了請求的操作後,再回過頭來對它進行處理。輪詢 polling 可能會是一種解決辦...
Linux 核心學習 6 中斷和異常處理
配置功能選項 中斷流程 連線ioapic引腳的裝置觸發中斷 檢測delivery status是否為0,不是0則等待,否則設其為1 sent pending 將中斷傳送至對應的cpu cpu響應中斷 對於level觸發的中斷,設定irr為1,並等待cpu觸發eoi,再將irr復位0 delivery...