中斷與中斷描述符表
阿新 • • 發佈:2022-12-11
中斷和異常
中斷,也叫做非同步中斷,由外部裝置產生可以隨時打斷當前CPU的執行流程。通常分為。
- 可遮蔽中斷:由IO裝置產生的IRQ中斷。這類中斷可以通過將
%eflags
暫存器中的IF標誌置為0來遮蔽。 - 不可遮蔽中斷:比如記憶體不對齊,斷電等無法忽略的外部訊號。
異常,也叫做同步中斷,中斷訊號在CPU執行完某個指令後產生並接收到。通常分為。
- 故障(fault):通常可以恢復,恢復之後返回到引起異常的語句重新執行,比如缺頁故障。
- 陷阱(trap):可以恢復,恢復之後引起異常的指令應該已經完成,所以返回到下一條語句執行,比如用來實現系統呼叫的軟中斷INT指令。
- 終止(abort):不可恢復,不返回引起異常的地方,都是直接終止程序。
中斷描述符表
中斷髮生後,會根據當前的中斷向量號去查詢中斷描述符表,裡面的中斷描述符記錄了當前中斷的處理程式的地址資訊,這樣就可以正確跳轉到中斷處理程式了。
在中斷描述符表中,可以存放中斷門,陷阱門,呼叫門,任務門這幾種描述符。結構如下。
- Offset:中斷函式在段中的偏移地址。
- Selector:段選擇子。
- Arguments:呼叫門的引數。
- Type:門的型別。
- S:為0表示為系統段,這裡必須為0。
- DPL:門特權級。
- P:存在位,如果這一位為0,則此描述符為非法的。
門的型別如下。
系統段型別 | type值 | 說明 |
---|---|---|
未定義 | 0000 | 保留 |
可用的80286TSS | 0001 | 僅限80286,任務狀態段 |
LDT | 0010 | 區域性描述符表 |
忙碌的80286TSS | 0011 | 僅限80286 |
80286呼叫門 | 0100 | 僅限80286 |
任務門 | 0101 | |
80286中斷門 | 0110 | 僅限80286 |
80286陷阱門 | 0111 | 僅限80286 |
未定義 | 1000 | 保留 |
可用的80386TSS | 1001 | 386以上的CPU的任務狀態段 |
未定義 | 1010 | 保留 |
忙碌的80386TSS | 1011 | |
80386呼叫門 | 1100 | 386以上CPU的呼叫門 |
未定義 | 1101 | 保留 |
中斷門 | 1110 | 386以上CPU的中斷門 |
陷阱門 | 1111 | 386以上CPU的陷阱門 |
中斷門和陷阱門的區別
它們之間的唯一區別就是中斷門在中斷觸發的時候會自動將%eflags
中的IF值0,頻閉外部中斷,以免被打斷。陷阱門則不會。
中斷處理完畢後,執行iret
指令會自動恢復之前壓入棧的%eflags
的值。
中斷流程
- 發生異常後,先查詢中斷描述符表,找到對應的描述符,一般而言不檢查門描述符裡面的DPL,除了用軟中斷int n和單步中斷int3,以及into引發的中斷和異常。這時候需要CPL必須小於等於DPL,也就是防止使用者態程式隨便呼叫核心的一些中斷。
- 檢查段許可權:將目的碼段描述符中的DPL與CPL比較,目標段的DPL必須小於或等於CPL。也就是說,通過中斷門時只允許保持或提升CPU的執行級別。失敗都會產生一次一般保護錯誤(General protection fault,GPF)。
- 儲存現場:如果當前的程式優先順序CPL和目的碼段DPL的一致,那麼直接將中斷現場壓入當前的棧。如果發生了優先順序提升,那麼切換到對應優先順序的棧空間,在那裡去儲存現場。可以通過TSS中儲存的各個優先順序的棧地址來知道具體切換到哪個棧空間去。
- 執行中斷程式並從中斷處理程式中返回:從棧中依次彈出Error Code(只有異常8-14以及異常17硬體才會壓入錯誤碼,其他的不會)和EIP和CS以及EFLAGS暫存器的值。然後進行棧恢復,判斷當前的特權級別和彈出的CS選擇子的特權級別,如果不同,說明之前有過棧切換,從棧中再彈出ESP和SS暫存器的值。