【計算機組成原理】中斷和輸入輸出

NO IMAGE

前言

這篇文章,我把中斷異常、輸入輸出,兩個部分放到一起,因為它們之間的聯絡實在很深。

中斷和異常

在程式執行時,系統內部,外部或者程式本身出現一些需要特殊處理的“事件”,CPU立即強行中斷當前程式,並改變機器狀態來執行一段處理這個“事件”的程式,然後再回來繼續執行之前的程式。這種機制,就叫中斷(異常)。

早期的計算機,只要做做計算任務就行了,與外界的互動非常簡單,但隨著不斷的發展,互動方式越來越豐富,中斷機制不斷顯示出了它的重要性。

中斷的具體過程

內部中斷和外部中斷:

  • 內部中斷就是CPU內部的不可遮蔽的中斷,在x86的真實模式下,有斷點,單步,溢位,除零中斷。其中,除零中斷會自動觸發,其餘的中斷一般需要用顯式的方式在程式中寫明,如果滿足條件則觸發。
  • 外部中斷,就是與外部裝置互動的中斷。比如BIOS中斷,DOS中斷,都是一種外部中斷,它們提供的都是一些功能性的中斷,比如輸出輸出。顯然這些也是需要你在程式裡顯示呼叫的。

過程:

  1. 關中斷。CPU關閉中斷(標誌暫存器中的IF位),不允許外部中斷。
  2. 保護斷點。把中斷處的指令地址壓入堆疊。
  3. 識別中斷源。CPU中斷處理器來確定中斷號,找到中斷程式的入口地址。
  4. 保護現場。把中斷處指令相關的暫存器以及標誌暫存器都要入堆疊。
  5. 轉到中斷服務程式入口開始執行。
  6. 恢復現場並返回。把IP,等暫存器都彈棧,然後執行中斷返回指令。

中斷向量表。

  • 真實模式下,中斷向量表就放在儲存器的最低地址區域。CPU中斷處理電路先找到中斷號,然後將對應的中斷向量裡的內容,分別放入IP和CS暫存器中。
  • IA-32的保護模式下的訪存方式不同了,同時CS暫存器的使用方式不同了,以前是直接放段基址,現在是放描述符,描述符表的起始地址是通過一個新的暫存器GDTR來儲存的,所以這種模式下,訪問儲存器的方式就變成了,通過CS暫存器的值查GDT,然後從表項中提取段基址和偏移,放入相應的暫存器,再對記憶體定址。所以,中斷也是類似的,通過IDTR和IDT來獲得CS和EIP的值,然後再次用GDTR和GDT的配合,來真正找到中斷入口地址。保護模式確實很繁瑣。

一個突然想到的問題:
我們前面講了流水線CPU,一個流水中通常都是包含了多條正在執行的指令,在中斷來臨的時候,那些未執行完的指令怎麼處理呢?

我覺得應該把那些未執行完的指令全部清空。不過後來,我在《現代作業系統》這本書裡,找到了答案,作者說會把中斷分為精確中斷和不精確中斷,前者就是我的猜想那樣,會把那些未執行完的指令造成的所有影響都撤銷,而後者更復雜,作業系統編寫者也為此頭疼。

輸入和輸出

早期的計算機,CPU處理輸入輸出的方式非常簡單,就是和讀寫儲存器的方式一樣,往地址匯流排上傳個地址,控制匯流排上傳個讀寫訊號,資料匯流排上傳資料。但是外部裝置種類和要求不同的時候,這種方式就不靠譜了。於是電腦科學家們就想出了很多方法。

I/O介面:
I/O介面是一塊晶片,有資料暫存器,狀態暫存器等,它與不同的裝置控制器相連,並在CPU與它們之間傳遞資料。這樣就能統一的管理輸入輸出裝置,消除了外設和CPU之間的速度差異,CPU也能繼續保持原來的方式讀寫了。通常,會有多個I/O介面。

I/O介面的編址方式:
CPU要訪問I/O埠(這裡埠指那些資料暫存器),就需要給這些埠編址。有兩種方式,與儲存器分開編址和與儲存器統一編址,前者是x86體系的實現,後者是ARM,MIPS等體系的實現。

I/O介面傳輸的控制方式:

  • 無條件傳送方式。CPU直接使用指令與外設傳遞資料,不查詢外設的工作狀態。
  • 程式查詢傳送方式。CPU通過執行一段迴圈的查詢程式,如果發現外設已準備就緒,才開始傳輸。
  • 中斷控制方式。發出傳輸指令,然後CPU繼續執行其他指令,I/O介面會主動發起中斷訊號。不同的外設發出的中斷訊號會被中斷控制器按優先順序或者某種設定進行處理,所以不同擔心衝突的發生。
  • DMA方式。DMA控制器來幫助CPU“指揮”資料在I/O介面與記憶體之間的傳輸。CPU只要設定DMAC的內部配置暫存器就好了。有些裝置對I/O要求很高,通常會在自己的I/O介面晶片中自帶DMAC。