1. 程式人生 > 其它 >linux系統中斷詳解

linux系統中斷詳解

最近為了解決風控問題,一直在研究linux的系統核心,經過一段時間的學習,先整理出一份關於linux中斷的小記。
1.什麼是中斷?
計算機cpu在執行task時,不可能每次都將任務執行完畢,會因為各種不同的場景而暫停執行,所謂中斷就是這個暫停執行的過程。
2.中斷算是一種錯誤嗎?
嚴格來說,中斷當然算是執行錯誤的一種,但是,由於其不可避免,程式開發者自然可以將其視為一種機制,加以運用,反而更容易幫助我們完成現實功能的實現。
3.中斷的分類
從產生原因上看,中斷可以分為軟體中斷和硬體中斷,而從類別劃分上看,也可以氛圍有出錯碼中斷和無出錯碼中斷。二者並不排斥,比如說,中斷分類存在int0~int255中,其中int0 ~ int31 表示軟體中斷,int32 ~ int255: 可由使用者自己設定。其中int32 ~ int47 對應8259A的IRQ0 ~ IRQ15中斷。需要注意的是,int128 為系統呼叫中斷(system_call)。
如果大家有看過核心原始碼或者其他彙編程式碼,會發現組合語言在呼叫c函式時,就是使用system_call,由此可見,呼叫其他函式,也是一種中斷。這裡不止侷限於linux系統,其中中斷邏輯囊括所有計算機邏輯執行邏輯,其最基礎的實現邏輯就是計算機0/1與或邏輯,屬於機器語言中最低階也是最高效的展現形式。
4.中斷時堆疊變化情況
堆疊相關知識此處不做介紹,不瞭解的同學可以自行查詢一下相關資料。

上圖可以非常清楚的展示中斷髮生時堆疊的變化情況。即中斷髮生前,需要將圖中的資訊按照先後順序,壓入中斷處理程式的堆疊中。下面進行具體的分析:
SS(stack segment): 堆疊段
ESP(extended stack pointer): 堆疊指標
EFLAGS : 狀態標誌暫存器
CS(code segment): 程式碼段
EIP(extended instruction pointer) : 中斷後要執行的下一條指令的地址
1)有/無 出錯碼:我們只需知道,對於某些中斷,比如:int0(無錯誤碼) 是不需要儲存出錯碼的,而像int8等中斷是需要儲存出錯碼的。所以對於不同的中斷,堆疊變化不同。需要儲存出錯碼的,必須在堆疊最後壓入出錯碼。
2)有/無 優先順序變化:如果中斷髮生前處於使用者態(優先順序3級),發生中斷時需要變為核心態(優先順序

0級),我們稱其為中斷時的優先順序發生了變化。對於優先順序變化的中斷,需要在堆疊的一開始壓入 SS 和 ESP , 它們分別代表使用者態下的堆疊段和堆疊指標。
這裡需要解釋一下,為什麼中斷髮生時,需要先把資訊資料壓入棧中,主要是為了中斷髮生後,可以從棧中取出,從而執行中斷時,可以從棧中獲取到之前的資料,類似於一個邏輯上下文的處理。
中斷過程就是 “中斷前,將當前資料壓入堆疊” -> “asm.s 呼叫 traps.c 處理中斷程式”-> “中斷完成後,將資料壓出堆疊,恢復狀態”
5.中斷處理檔案,asm.s
第四條最後,提到了倆個檔案,asm.s和traps.c。這裡的.c檔案,大家應該都可以猜到,就是c語言編寫的函式檔案,asm.s則涵蓋了int0 ~ int15中除int7,int14之外的一共14箇中斷處理程式。還記得嗎?它們都是Intel固定設定的軟體中斷。
asm.s 程式的核心是以下兩個函式:no_error_code和error_code。他們分別表示的是無出錯碼中斷和有中斷碼中斷。
no_error_code原始碼如下

error_code原始碼如下


6.中斷處理檔案traps.c
traps.c是一個c語言編寫的實現檔案,其中的函式多用於給asm.s檔案呼叫。在asm.s檔案的彙編程式碼中,call *****即為呼叫c函式,但是被呼叫的函式需要在檔案頂部的“.globl”進行宣告才能呼叫。
traps.c的核心函式是die函式,其原始碼如下:

die函式的主要功能是列印錯誤資訊,對於Inter這些固定的軟體中斷(int0 ~ int16),當發生時,我們所做的也就是打印出中斷的名稱,出錯號,暫存器資訊,程序資訊等等。