1、中斷和異常的差別
中斷:一般由外部裝置引起;
異常:cpu執行完某條指令之後,cpu控制單元産生,一般由程式設計錯誤引起。
2、中斷向量
0~255
0~31:異常和不可屏蔽中斷
32~47:可屏蔽中斷
48~255:軟中斷
linux使用一個軟中斷(0x80)作為系統核心函數的系統調用接口。
硬體中斷IRQ0~IRQ15被關聯到了中斷向量32.。。47.
2、中斷描述表
中斷描述符表中,每個向量在表中有相應的中斷或者異常處理程式的入口位址。核心在允許中斷發生前,必須先适當的初始化IDT
中斷描述符表的作用:将中斷向量和中斷處理程式一一對應起來。
IDT表的大小為:256*8.因為linux系統中有256個中斷和異常,是以該表共有256項,每一項有8個位元組。

16-31是段選擇符,0-15和48-64組合起來形成32位偏移量。
40-43表示描述符的類型:01110中斷描述符;00101任務門描述符,01111陷阱門描述符。在這裡我們主要研究中斷門和陷阱門。而這個描述符也是中斷門和異常門唯一的差別。
DPL:等于0或者3.0是特權模式。使用者态(DPL=3).
目前的執行等級被儲存在CPL寄存器中。控制單元比較CPL和IDT中的DPL字段,如果DPL字段的值較大,則中斷被執行。
中斷描述符表是存在于記憶體中的,是以,怎麼尋址到這張表的呢?
linux中有一個寄存器IDTR(48位)其中32位是段基址,16位是段限。(從這裡我們可以看出,整個IDT表的大小為64k,而每個表項是8位元組,所有最多有8k的表項,但是系統中隻有256個表項被使用)
linux中有一個GDT表,記錄了所有的段基址,段屬性以及段長。
我們是怎麼根據中斷向量号(0~255)找到中斷服務程式的入口位址呢?
在IDT中,每個表項都是一個門。我們首先根據中斷号找到中斷門,然後根據中斷門中的段選擇符(16位:高十三位是索引,最低兩位是DPL),索引到GDT中的相應表項。進而找到該中斷服務程式所在的段基址。然後該段基址和中斷門中的偏移量找到中斷服務程式入口位址。
在這裡有一個安全性的問題。當找到段基址之後,該段基址中有一個DPL,我們需要将目前特權級CPL(存放在cs寄存器中的低兩位)與段描述符(存放在GDT中)的描述符的特權級DPL進行比較,如果CPL比較小,則産生異常。
對于程式設計異常,則做進一步安全檢查,比較CPL與處于IDT中的門描述符中的DPL,如果DPL小,則産生一個“General protection”異常。
對于上面這句話總結一下:意思是在中斷門(異常門)中,有兩個DPL,分别位于段選擇符以及(46,45bit)中。
我們都知道這個段選擇符最終是要裝載到cs寄存器中,而偏移量是要裝載到eip寄存器中。那麼這個中斷到底能不能執行,我們首先要将這個段選擇符中的DPL和目前cs寄存器中的CPL進行比較(低兩位);
如果要還要考慮程式設計異常,那麼該中斷門中的DPL也要進行相應的檢查。
linux中有很多體系結構相關的函數在IDT中插入門:
set_trap_gate(n,addr).
在IDT的第n個表項插入一個陷阱門。門中的段選擇符設定成為核心代碼的段選擇符,偏移量設定為異常程式處理位址(addr),同時DPL字段設定為0.
在linux核心源碼的實作上,idt_descr變量(6個位元組制定了IDT的位置和大小)。idt_table存放了IDT表。
在linux核心中,首先用一個空函數ignore_int來統一初始化中斷處理程式,然後在start_kernel中對IDT進行第二次初始化。trap_init()函數将異常處理程式插入到IDT中。插入的函數包括:
set_trap_gate()(DPL=0),set_intr_gate()(DPL=0),set_system_gate()(DPL=3,陷阱門),set_system_intr_gate()(DPL=3),set_task_gate()(中斷門,門選擇符是TSS全局描述符表的指針,該TSS中包含被激活的函數,偏移量設定為0,DPL=3),
異常處理程式三個标準的結構:
在核心堆棧中儲存大多數寄存器的内容;
用進階c語言處理異常;
通過ret_from_exception()函數從異常處理程式退出。
分析:int指令發送一個中斷信号,然後,系統就會查找IDT->GDT,找到異常處理程式,執行完之後傳回。
中斷:
IO中斷;時鐘中斷;處理器間中斷;
中斷處理程式的靈活性:
IRQ共享;
IRQ動态配置設定;
中斷處理程式要執行的操作:緊急的;非緊急的;非緊急可延遲的;
IO中斷處理流程:IRQn->IDT[32+N]->interrupt[n]->do_IRQ[n]->中斷服務例程1。。。中斷服務例程n。
每一個中斷向量(中斷門)對應一個irq_desc描述符。