1. 程式人生 > >Linux核心中斷和異常分析(上)

Linux核心中斷和異常分析(上)

中斷,通常被定義為一個事件。打個比方,你燒熱水,水沸騰了,這時候你要去關掉燒熱水的電磁爐,然後再去辦之前手中停不下來的事情。那麼熱水沸騰就是打斷你正常工作的一個訊號機制。當然,還有其它的情況,我們以後再做分析。

      中斷也就是這樣產生的,中斷分為同步中斷還有非同步中斷。

      同步中斷在Intel的手冊中被稱為異常,而非同步中斷被稱作中斷。打個比方在ARM處理器的異常種類就有不少,有未定義指令異常,軟中斷異常,快中斷異常等等。異常是由程式錯誤產生的,或者是核心必須處理的異常條件產生的。如果你曾經學過微控制器,那麼你一定會清楚,51微控制器的P32,P33是外部中斷0和1,假設當你在程式中開啟了外部中斷0,然後在中斷中執行了相應的程式,這時你在外部中斷0的一腳連線一個按鍵,這時候你按下去P30這個引腳就會產生一箇中斷。那麼中斷服務程式就會響應你的操作,比如點亮一個LED燈,或者說蜂鳴器叫一下等等。

      那麼在linux核心中的中斷其實也是和微控制器類似的,只不過linux核心的中斷定義的比較豐富,但是基本思想還是一樣的。linux核心處理中斷有一種叫做中斷訊號的機制。它的作用就是當一箇中斷訊號到來時,CPU必須停止它當然正在做的事情,然後切換到一個新的活動,為了做到這一點,核心態堆疊儲存的程式計數器的當前值,其實就是eip和cs暫存器的儲存資料,然後把中斷相關型別的一個地址放到一個程式計數器當中去。

     其實在核心中,中斷這樣的切換機制很像程序的排程,上下文切換這樣的機制,但是依然存在著一個非常明顯的差異,那就是中斷或者異常在處理的程式碼並不是一個程序。

     中斷訊號的來臨必將會引起中斷的處理,那麼中斷處理必須要滿足以下的約束:

1、linux核心在響應中斷以後必須要進行的操作分為兩部分:我們把非常重要的,非常緊急的處理程式讓核心立即去執行。剩下的有延時的部分就讓它後面再去執行。這樣也就驗證了水沸騰,而人停下手中的事去關電磁爐,再回去做他的事一樣的道理。

2、中斷編寫的程式必須編寫成可以使核心控制的路徑能以巢狀的方式來執行,或者說,當最後一個核心控制路徑終止的時候,核心必須能恢復被中斷程序的執行,或者說,中斷訊號已經導致了程序重新排程,核心能切換到另外一個程序。這是我們分析的另外一種情況,水開了,人去關電磁爐,然後人接著做事,這是第一種情況。水開了,人去關電磁爐,接下來門鈴響了,客人來了,你必須去迎接客人,然後就打斷了你之前在做的事情,也就是客人來了打斷了你正在做的這件事進入到與陪客的階段。

3、在臨界區中,中斷必須要被禁止。臨界區其實就是加鎖和去鎖的實現。程式設計師將非常關鍵的步驟放進臨界區,就是為了防止中斷或者其它的訊號去影響到它,其實在核心中這樣的步驟是有必要的。臨界區的程式碼必須在短時間內被執行,而不應該出現延時的操作,且必須儘可能的去限制這樣的臨界區,因為,核心在處理中斷程式的時候,應該是在大部分時間以開中斷的方式去執行。

在intel的文件中,中斷和異常通常分為幾類:中斷有可遮蔽的,不可遮蔽的。異常有處理器探測異常,這就包括故障的產生,陷阱,異常的中止,還有程式設計異常的狀況。每個中斷和異常都是由0-255之間的一個數來標識。intel管這東西叫向量。

      其實在ARM中就有那麼一張表叫異常向量表,那就是我剛剛文章裡說過的那幾個。


在linux中也有這麼一張表: