為了方便說明,這里我們將PIC和APIC統(tǒng)稱為中斷控制器。中斷控制器是作為中斷(IRQ)和CPU核之間的一個橋梁而存在的,每個CPU內(nèi)部都有一個自己的中斷控制器,中斷線并不是直接與CPU核相連,而是與CPU內(nèi)部或外部的中斷控制器相連。而為什么叫做可編程中斷控制器,是因為其本身有一定的寄存器,CPU可以通過操作設置中斷控制器屏蔽某個中斷引腳的信號,實現(xiàn)硬件上的中斷屏蔽。中斷控制器也可以級聯(lián)提供更多的中斷線,具體如下:
如上圖,CPU的INTR與中斷控制器的INT相連,INTA與ACK相連,當一個外部中斷發(fā)生時(比如鍵盤中斷IRQ1),中斷控制器與CPU交互操作如下:
在linux內(nèi)核中,用struct irq_chip結構體描述一個可編程中斷控制器,它的整個結構和調(diào)度器中的調(diào)度類類似,里面定義了中斷控制器的一些操作,如下:
在中斷系統(tǒng)中有兩個名字很相像的結構,就是中斷描述符表和中斷描述符數(shù)組。這里我們先說說中斷描述符表。 一個系統(tǒng)中的中斷和異常加起來一共是256個,它們以向量的形式保存在中斷描述符表中,每一個向量是8字節(jié)(整個表大小就是8 x 256=2048字節(jié)),其主要保存著權限位和向量對應的中斷或異常處理程序的入口地址。而一般的,linux會將中斷描述符表中的0~31用于非屏蔽中斷和異常,其他的中斷用于32~255之間。CPU把中斷描述符表的向量類型分為三種類型:任務門、中斷門、陷阱門。CPU為了防止惡意程序訪問中斷,限制了中斷門的權限,而在某些時候,用戶程序又必須使用中斷,所以Linux把中斷描述符的中斷向量類型改為了5種:中斷門,系統(tǒng)門,系統(tǒng)中斷門,陷阱門,任務門。
當我們發(fā)生異常或中斷時,系統(tǒng)首先會判斷權限字段(安全處理),權限通過則進入指定的處理函數(shù),而所有的中斷門的中斷處理函數(shù)都是同一個,它首先是一段匯編代碼,匯編代碼操作如下:
每個能夠產(chǎn)生中斷的設備或者模塊都會在內(nèi)核中注冊一個中斷服務例程(ISR),當產(chǎn)生中斷時,中斷處理程序會被執(zhí)行,在中斷處理程序中,首先會保存中斷向量號和上下文,之后執(zhí)行中斷線對應的中斷服務例程。對于CPU來說,中斷線是非常寶貴的資源,而由于計算機的發(fā)展,外部設備數(shù)量和種類越來越多,導致了中斷線資源不足的情況,linux為了應對這種情況,實現(xiàn)了兩種中斷線分配方式,分別是:共享中斷線,中斷線動態(tài)分配。
多個設備共用一條中斷線,當此條中斷線發(fā)生中斷時,因為不可能預先知道哪個特定的設備產(chǎn)生了中斷,因此,這條中斷線上的每個中斷服務例程都會被執(zhí)行,以驗證是哪個設備產(chǎn)生的中斷(一般的,設備產(chǎn)生中斷時,會標記自己的狀態(tài)寄存器,中斷服務例程通過檢查每個設備的狀態(tài)寄存器來查找產(chǎn)生中斷的設備)。
一條中斷線在可能使用的時刻才與一個設備驅(qū)動程序關聯(lián)起來,這樣一來,即使幾個硬件設備并不共享中斷線,同一個中斷向量也可以由這幾個設備在不同時刻運行。
共享中斷線的分配方式是比較常見的,一次典型的基于共享中斷線的中斷處理流程如下:
由于中斷處于中斷上下文中,所以在中斷處理過程中,會有以下幾個特性:
中斷描述符用于描述IRQ線的屬性與狀態(tài),每個IRQ都有它自己的中斷描述符,這些中斷描述符用一個數(shù)組保存, 這個數(shù)組就是中斷描述符數(shù)組,整個中斷描述符數(shù)組長度為NR_IRQS(通常為224)項。當產(chǎn)生一個中斷或者異常時,首先會從中斷描述符表中獲取到一個中斷向量號時(此中斷向量號有可能表示中斷,也可能表示的是一個異常),如果是一個中斷導致的,會執(zhí)行do_IRQ()函數(shù),而在do_IRQ()函數(shù)中,會根據(jù)中斷向量號,從中斷描述符數(shù)組中獲取對應的中斷描述符,如下圖:
中斷服務例程用于描述一個設備的中斷處理(區(qū)別與中斷處理函數(shù)),每個申請了中斷的外部設備都會有一個中斷服務例程,其作用就是執(zhí)行對應設備的中斷處理。當多個設備共享IRQ線時,內(nèi)核會將此IRQ線上所有設備的中斷服務例程組織成一個鏈表并保存在中斷描述符中,當此IRQ線產(chǎn)生中斷時,中斷處理函數(shù)會依次執(zhí)行此IRQ線上的中斷服務例程。內(nèi)核使用struct irqaction描述一個中斷服務例程:
此數(shù)組包含NR_CPUS個元素,系統(tǒng)中每個CPU對應數(shù)組中的一個元素。每個元素的類型為irq_cpustat_t,其包含幾個計數(shù)器和內(nèi)核記錄CPU正在做什么的標志。
到此,在中斷處理中所涉及的幾個重要的數(shù)據(jù)結構已經(jīng)說明,其最主要的數(shù)據(jù)結構為:中斷描述符(struct irq_desc),中斷控制器描述符(struct irq_chip),中斷服務例程(struct irqaction)。它們的組織形式如下: