這些問題並不複雜,但它們深入涉及到系統軟體工作的本質。為了準確回答這些問題,我們需要透徹理解作業系統的行為模型,包括效能、安全和除錯等方面。在該系列文章中,我們將以 Linux 為主舉例來幫助你建立作業系統的行為模型,OS X 和 Windows 在必要的時候也會有所涉及。對那些深度探索者,我會在適當的時候給出 Linux 核心原始碼的連結。
這裡有一個基本認知,就是,在任意給定時刻,某個 CPU 上僅有一個任務處於活動狀態。大多數情形下這個任務是某個使用者程式,例如你的 Web 瀏覽器或音樂播放器,但它也可能是一個作業系統執行緒。可以確信的是,它是一個任務,不是兩個或更多,也不是零個,對,永遠是一個。
這聽上去可能會有些問題。比如,你的音樂播放器是否會獨佔 CPU 而阻止其它任務執行?從而使你不能開啟任務管理工具去殺死音樂播放器,甚至讓滑鼠點選也失效,因為作業系統沒有機會去處理這些事件。你可能會憤而喊出,“它究竟在搞什麼鬼?”,並引發騷亂。
此時便輪到中斷大顯身手了。中斷就好比,一聲巨響或一次拍肩後,神經系統通知大腦去感知外部刺激一般。計算機主機板上的晶片組同樣會中斷 CPU 執行以傳遞新的外部事件,例如鍵盤上的某個鍵被按下、網路資料包的到達、一次硬碟讀取的完成,等等。硬體外設、主機板上的中斷控制器和 CPU 本身,它們共同協作實現了中斷機制。
中斷對於記錄我們最珍視的資源——時間——也至關重要。計算機啟動過程中,作業系統核心會設定一個硬體計時器以讓其產生週期性計時中斷,例如每隔 10 毫秒觸發一次。每當計時中斷到來,核心便會收到通知以更新系統統計資訊和盤點如下事項:當前使用者程式是否已執行了足夠長時間?是否有某個 TCP 定時器超時了?中斷給予了核心一個處理這些問題並採取合適措施的機會。這就好像你給自己設定了整天的週期鬧鈴並把它們用作檢查點:我是否應該去做我正在進行的工作?是否存在更緊急的事項?直到你發現 10 年時間已逝去……
這些核心對 CPU 週期性的劫持被稱為滴答tick,也就是說,是中斷讓你的作業系統滴答了一下。不止如此,中斷也被用作處理一些軟體事件,如整數溢位和頁錯誤,其中未涉及外部硬體。中斷是進入作業系統核心最頻繁也是最重要的入口。對於學習電子工程的人而言,這些並無古怪,它們是作業系統賴以執行的機制。
說到這裡,讓我們再來看一些實際情形。下圖示意了 Intel Core i5 系統中的一個網路卡中斷。圖片中的部分元素設定了超鏈,你可以點選它們以獲取更為詳細的資訊,例如每個裝置均被連結到了對應的 Linux 驅動原始碼。
連結如下:
讓我們來仔細研究下。首先,由於系統中存在眾多中斷源,如果硬體只是通知 CPU “嘿,這裡發生了一些事情”然後什麼也不做,則不太行得通。這會帶來難以忍受的冗長等待。因此,計算機上電時,每個裝置都被授予了一根中斷線,或者稱為 IRQ。這些 IRQ 然後被系統中的中斷控制器對映成值介於 0 到 255 之間的中斷向量。等到中斷到達 CPU,它便具備了一個完好定義的數值,異於硬體的某些其它詭異行為。
相應地,CPU 中還存有一個由核心維護的指標,指向一個包含 255 個函式指標的陣列,其中每個函式被用來處理某個特定的中斷向量。後文中,我們將繼續深入探討這個陣列,它也被稱作中斷描述符表(IDT)。
每當中斷到來,CPU 會用中斷向量的值去索引中斷描述符表,並執行相應處理函式。這相當於,在當前正在執行任務的上下文中,發生了一個特殊函式呼叫,從而允許作業系統以較小開銷快速對外部事件作出反應。考慮下述場景,Web 伺服器在傳送資料時,CPU 卻間接呼叫了作業系統函式,這聽上去要麼很炫酷要麼令人驚恐。下圖展示了 Vim 編輯器執行過程中一箇中斷到來的情形。
此處請留意,中斷的到來是如何觸發 CPU 到 Ring 0 核心模式的切換而未有改變當前活躍的任務。這看上去就像,Vim 編輯器直接面向作業系統核心產生了一次神奇的函式呼叫,但 Vim 還在那裡,它的地址空間原封未動,等待著執行流返回。
這很令人振奮,不是麼?不過讓我們暫且告一段落吧,我需要合理控制篇幅。我知道還沒有回答完這個開放式問題,甚至還實質上翻開了新的問題,但你至少知道了在你讀這個句子的同時滴答正在發生。我們將在充實了對作業系統動態行為模型的理解之後再回來尋求問題的答案,對 Web 瀏覽器情形的理解也會變得清晰。如果你仍有問題,尤其是在這篇文章公諸於眾後,請儘管提出。我將會在文章或後續評論中回答它們。下篇文章將於明天在 RSS 和 Twitter 上釋出。