1. 程式人生 > 其它 >中斷與中斷描述符表

中斷與中斷描述符表

中斷和異常

中斷,也叫做非同步中斷,由外部裝置產生可以隨時打斷當前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的值。

中斷流程

  1. 發生異常後,先查詢中斷描述符表,找到對應的描述符,一般而言不檢查門描述符裡面的DPL,除了用軟中斷int n和單步中斷int3,以及into引發的中斷和異常。這時候需要CPL必須小於等於DPL,也就是防止使用者態程式隨便呼叫核心的一些中斷。
  2. 檢查段許可權:將目的碼段描述符中的DPL與CPL比較,目標段的DPL必須小於或等於CPL。也就是說,通過中斷門時只允許保持或提升CPU的執行級別。失敗都會產生一次一般保護錯誤(General protection fault,GPF)。
  3. 儲存現場:如果當前的程式優先順序CPL和目的碼段DPL的一致,那麼直接將中斷現場壓入當前的棧。如果發生了優先順序提升,那麼切換到對應優先順序的棧空間,在那裡去儲存現場。可以通過TSS中儲存的各個優先順序的棧地址來知道具體切換到哪個棧空間去。
  1. 執行中斷程式並從中斷處理程式中返回:從棧中依次彈出Error Code(只有異常8-14以及異常17硬體才會壓入錯誤碼,其他的不會)和EIP和CS以及EFLAGS暫存器的值。然後進行棧恢復,判斷當前的特權級別和彈出的CS選擇子的特權級別,如果不同,說明之前有過棧切換,從棧中再彈出ESP和SS暫存器的值。

參考資料