歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux內核

Linux內核的中斷機制分析

摘要:本文主要從內核實現的角度分析了Linux 2.4.0內核的設備中斷流程。本文是為那些想要了解Linux I/O子系統的讀者和Linux驅動程序開發人員而寫的。

關鍵詞:Linux、中斷、設備驅動程序

申明:這份文檔是按照自由軟件開放源代碼的精神發布的,任何人可以免費獲得、使用和重新發布,但是你沒有限制別人重新發布你發布內容的權利。發布本文的目的是希望它能對讀者有用,但沒有任何擔保,甚至沒有適合特定目的的隱含的擔保。更詳細的情況請參閱GNU通用公共許可證(GPL),以及GNU自由文檔協議(GFDL)。

你應該已經和文檔一起收到一份GNU通用公共許可證(GPL)的副本。如果還沒有,寫信給:

The Free Software Foundation, Inc., 675 Mass Ave, Cambridge,MA02139, USA

歡迎各位指出文檔中的錯誤與疑問。

§5.1 I386的中斷與異常

中斷通常被分為“同步中斷”和異步中斷兩大類。同步中斷是指當指令執行時由CPU控制單元產生的中斷,之所以稱為“同步中斷”是因為只有在一條指令中止執行後CPU才會發出這類中斷信號。而異步中斷則是指由其他硬件設備依照CPU時鐘隨機產生的中斷信號。

在Intel 80x86 CPU手冊中,同步中斷和異步中斷也被分別稱為“異常(Exception)”和“中斷(Interrupt)”。Intel又詳細地把中斷和異常細分為以下幾類:

(1)中斷

1. 可屏蔽中斷(Maskable Interrupt):這類中斷被送到CPU的INTR引腳,通過清除eflag寄存器的IF標志可以關閉中斷。

2. 不可屏蔽中斷(Nonmaskable Interrupt):被送到CPU的NMI引腳,通常只有幾個危急的事件,如:硬件故障等,才產生不可屏蔽中斷信號。寄存器eflag中的IF標志對這類中斷不起作用。

(2)異常

1. 處理器探測異常(Processor-detected exception):當CPU執行一條指令時所探測到的一個反常條件所產生的異常。依據CPU控制單元產生異常時保存在內核態堆棧eip寄存器的值,這類異常又可以細分為三種:

n 故障(Fault):保存在eip中的值是引起故障的指令地址,因此但異常處理程序結束後,會重新執行那條指令。“缺頁故障”是這類異常的一個常見例子。

n 陷阱(Trap):保存在eip中的值是一個指令地址,但該指令在引起陷阱的指令地址之後。只有當沒有必要重新執行已執行過的指令時,才會觸發trap,其主要用途是調試程序。

n 異常中止(Abort):當發生了一個嚴重的錯誤,致使CPU控制單元除了麻煩而不能在eip寄存器中保存有意義的值。異常中止通常是由硬件故障或系統表中無效的值引起的。由CPU控制單元發生的這個中斷是一種緊急信號,用來把CPU的執行路徑切換到異常中止的處理程序,而相應的ISR通常除了迫使受到影響的進程中止外,別無選擇。

2. 編程異常(Programmed Exception):通常也稱為“軟中斷(software interrupt)”,是由編程者發出中斷請求指令時發生的中斷,如:int指令和int3指令。當into(檢查溢出)和bound(檢查地址越界)指令檢查的條件不為真時,也引起編程異常。CPU控制單元把編程異常當作Trap來處理,這類異常有兩個典型的用途:一、執行系統調用;二、給調試程序通報一個特定條件。

5.1.1 中斷向量

每個中斷和異常都可以用一個0-255之間的無符號整數來標識,Intel稱之為“中斷向量(Interrupt Vector)”。通常,不可屏蔽中斷和異常的中斷向量是固定的,而可屏蔽中斷的中斷向量則可以對中斷控制器進行編程來改變。I386 CPU的256個中斷向量是這樣分配的:

1. 從0-31這一共32個向量用於異常和不可屏蔽中斷。

2. 從32-47這一共16個向量用於可屏蔽中斷,分別對應於主、從8259A中斷控制器的IRQ輸入線。

3. 剩余的48-255用於標識軟中斷。

Linux全部使用了0-47之間的向量。但對於48-255之間的軟中斷向量,Linux只使用了其中的一個,即用於實現系統調用的中斷向量128(0x80)。當用戶態下的進程執行一條int 0x80匯編指令時,CPU切換到內核態,以服務於系統調用。

Linux在頭文件include/asm-i386/hw_irq.h中定義了宏FIRST_EXTERNAL_VECTOR來表示第一個外設中斷(即8259A的IRQ0)所對應的中斷向量,此外還定義了SYSCALL_VECTOR來表示用於系統調用的中斷向量。如下所示:

/*

* IDT vectors usable for external interrupt sources start

* at 0x20:

*/

#define FIRST_EXTERNAL_VECTOR 0x20

#define SYSCALL_VECTOR 0x80

5.1.2 I386的IDT

i386 CPU的IDT表一共有256項,分別對應每一個中斷向量。每一個表項就是一個中斷描述符,用以描述相對應的中斷向量,中斷向量就是該描述符在IDT中的索引,每一個中斷描述符的大小都是8個字節。根據INTEL的術語,中斷描述符也稱為“門(Gate)”。

中斷描述符有下列4種類型:

(1)任務們(Task Gate):包含了一個進程的TSS段選擇符。每當中斷信號發生時,它被用來取代當前進程的那個TSS段選擇符。Linux並沒有使用任務們。任務們的格式如下:

(2)中斷門(Interrupt Gate):中斷門中包含了一個段選擇符和一個中斷處理程序的段內偏移。注意,當I386 CPU穿越一個中斷門進入相應的中斷處理程序時,它會清除eflag寄存器中的IF標志,從而屏蔽接下來可能發生的可屏蔽中斷。

(3)陷阱門(Trap Gate):與中斷門類似,不同之處在於CPU通過陷阱門轉入中斷處理程序時不會清除IF標志。

(4)調用門(Call Gate):Linux並沒有使用調用門。

這三種門的格式如圖5-2所示。

5.1.3 中斷控制器8259A

我們都知道,PC機中都使用兩個級聯的8359A PIC(Programmable Interrupt Controller,可編程中斷控制器,簡稱PIC)來管理來自系統外設的中斷信號。每個8259A PIC提供8根IRQ(Interrupt ReQuest,中斷請求,簡稱IRQ)輸入線。在級聯方式中,Master 8259A PIC(第一個PIC)的中斷信號輸入線IR2用於級聯Slave 8259A PIC(第二個PIC)的INT引腳,因此兩個8259A一共可以提供15根可用的IRQ輸入線。如下圖所示:

圖5-3 主、從8259A中斷控制器的級聯

5.1.3.1 8259A PIC的基本原理

Copyright © Linux教程網 All Rights Reserved