《Linux核心設計與實現》讀書筆記(4)— 中斷和中斷處理常式

來源:互聯網
上載者:User

中斷和中斷處理常式

1.中斷

    中斷本質上是一種特殊的電訊號,由硬體裝置發向處理器。處理器接收到中斷後,會馬上向作業系統反映此訊號的到來,然後由OS負責處理這些新到來的資料。硬體裝置產生中斷的時候並不考慮與處理器的時鐘同步,核心隨時可能因為新到來的中斷而被打斷。不同的裝置對應的中斷不同,都通過一個唯一的數位識別碼,稱之為插斷要求(IRQ)線。

    在作業系統中,討論中斷就不得不提及異常。異常與中斷不同,它在產生時必須考慮與處理器時鐘同步。實際上,異常也常常稱為同步中斷。在處理器執行到由於編程失誤而導致的錯誤指令的時候,或者是在執行期間出現特殊情況,必須靠核心來處理的時候,處理器就會產生一個異常。因為許多處理器體繫結構處理異常與處理中斷的方式類似,因此,核心對它們的處理也很類似。

 

2.中斷處理常式

    在響應一個特定中斷的時候,核心會執行一個函數,該函數叫做中斷處理常式(interrupt handler)或插斷服務常式(interrupt service routine,ISR)。中斷處理常式通常不是和特定裝置關聯,而是和特定中斷關聯,也就是說,如果一個裝置可以產生多種不同的中斷,那麼該裝置就可以對應多個中斷處理常式,相應的,該裝置的驅動程式也就需要準備多個這樣的函數。

    中斷處理常式與其他核心功能的真正區別在於:中斷處理常式是被核心調用來響應中斷的,而它們運行於稱之為中斷內容相關的特殊上下文中。

    中斷處理常式一方面需要迅速和儘可能短的時間內完成中斷處理,另一方面,處理常式內的工作量也不小。所以把中斷處理切為兩個部分。中斷處理常式是上半部(top half)——接收到一個中斷,它就立即開始執行,但只做有嚴格時限的工作,例如對接收的中斷進行應答或複位硬體,這些工作都是在所有中斷被禁止的情況下完成的,能夠被允許稍後完成的工作延遲到下半部(bottom half)。

 

3.共用的中斷處理常式

    共用與非共用的處理常式差異有以下三處:

    1)request_irq()的參數flags必須設定SA_SHIRQ標誌,但只有在中斷棧當前未被註冊,或者在該棧上的所有登入處理常式都指定了SA_SHIRQ的情況下才會成功。

    2)對每個註冊的中斷處理常式來說,dev_id參數必須唯一。

    3)需要硬體的支援。

    核心接收一個中斷後,會依次調用在該中斷線上註冊的每一個處理常式。因此,一個處理常式必須知道它是否應該為這個中斷負責。如果與它相關的裝置並沒有產生中斷,那麼處理常式應該立即退出。

 

4.中斷上下文

    當執行一個中斷處理常式或下半部時,核心處於中斷上下文(interrupt context)中,中斷上下文具有較為嚴格的時間限制,因為它打斷了其他代碼(甚至打斷了其他中斷線上的另一個中斷處理常式),它應迅速簡潔,盡量不要使用迴圈去處理繁重的工作。另一方面,中斷處理常式擁有自己的棧,每個處理器一個,大小為一頁(32位為4KB,64位為8KB),稱之為中斷棧。中斷處理常式的編寫要注意這兩個方面。

 

5.中斷控制

    Linux核心提供了一組介面用於操作機器上的中斷狀態。這些介面為我們提供了能夠禁止當前處理順的中斷系統,或屏蔽掉整個機器的一條中斷線的能力。一般來說,控制中斷系統的原因歸根結底是需要提供同步。通過禁止中斷,可以確保某個中斷處理常式不會搶佔當前的代碼。然而,不管是禁止中斷還是禁止核心搶佔,都沒有提供任何保護機制來防止來自其他處理器的並發訪問。Linux支援多處理器,因此,核心代碼一般都需要擷取某種鎖,防止來自其他處理器對共用資料的並發訪問。擷取這些鎖的同時也伴隨禁止本地中斷。

    用于禁止或啟用當前處理器上的本地中斷的語句為:

    local_irq_disable() 和 local_irq_enable()

    直接使用這兩個語句禁止或啟用中斷都存在潛在危險,因為它們將無條件地禁止或啟用中斷,而不管中斷在開始時的狀態。因此,在禁止中斷之前儲存中斷系統的狀態會更加安全一些。相反,在準備啟用中斷時,只要把中斷恢複到它們原來的狀態。

    在某些情況下,只禁止整個系統中一條特定的中斷線就夠了,Linux提供了四個介面:

    void disable_irq(unsigned int irq);

    void disable_irq_nosync(unsigned int irq);

    void enable_irq(unsigned int irq);

    void synchronize_irq(unsigned int irq);

    前兩個函數禁止中斷控制器上指定的中斷線,即禁止給定中斷向系統中所有處理器的傳遞。另外,函數只有在當前正在執行的所有處理常式完成後,disable_irq()才能返回。函數disable_irq_nosync()不會等待當前中斷處理常式執行完畢。

    函數synchronize_irq()等待一個特定的中斷處理常式的退出。如果該處理常式正在執行,那麼該函數必須退出後才能返回。

    這些函數調用可以嵌套,但要記住在一條指定的中斷線上,對disable_irq()或disable_irq_nosync()的每次調用,都需要相應地調用一次enable_irq()。只有在對enable_irq()完成最後一次調用後,才真正啟用了中斷線。

    Linux提供兩個宏,用來瞭解中斷系統的狀態:

    in_interrupt() 和 in_irq()

    in_interrupt():如果核心處於中斷上下文中,它返回非0,說明核心此刻正在執行中斷處理常式,或者正在執行下半部處理常式。in_irq()只有在核心確實正在執行中斷處理常式時才返回非0。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.