1. 程式人生 > >Linux中斷上半部和下半部

Linux中斷上半部和下半部

前言
  cpu在執行程式時,如果有外部中斷觸發時,如定時器中斷、序列匯流排中斷等,cpu停止當前任務從而轉去響應中斷處理。對於中斷函式的處理,原則是儘快處理完事務並退出中斷,這一點也比較好理解,儘快處理中斷並返回,保證正常任務的執行,並q且能否響應其他事務的中斷,保證實時性和併發性。

  其實,在微控制器邏輯程式設計中已經使用過Linux中斷“上下部分”的思維,或者說,Linux中斷“上下半部”設計者靈感即源自最初的裸機程式設計。例如,在微控制器裸機程式設計中,需要通過串列埠(UART)進行資料通訊,對於接收資料情況下,在採用中斷方式接收時,我們一般會先將資料存放在一個快取(buf)中,中斷函式只負責將資料存入快取,而在主函式中獲取快取資料並處理。在這個過程中,中斷處理部分即將資料存入快取的動作為“中斷上半部”,當然還包括從暫存器獲取資料,改變暫存器狀態等。“中斷下半部”則是獲取快取資料並處理。

RTOS中斷處理


  從裸機程式設計上升到系統層面,微控制器執行實時系統(RTOS)。RTOS一般以執行緒為排程任務,沒有程序概念,但都會提供一套類似標準作業系統的 執行緒同步機制。此時,在設計中斷程式時,可以更好實現“上半部”和“下半部”,特別是“下半部”。以RT-Thread為例,實現一個串列埠中斷接收函式。上半部分負責將資料放入快取,並通過訊號量通知下半部分處理。下半部實現,可以建立一個處理執行緒,當獲得上半部訊號量時則排程執行緒進行處理資料,否則則掛起該執行緒,節約cpu資源。

Linux中斷
  不同於裸機程式設計,作業系統是多個程序和多個執行緒執行,巨集觀上達到並行執行的狀態,外設中斷則會打斷核心中任務排程和執行,及遮蔽其外設的中斷響應,如果中斷函式耗時過長則使得系統實時性和併發性降低。中斷原則是儘可能處理少的事務,而一些裝置中往往需要處理大量的耗時事務。為了提高系統的實時性和併發性,Linux核心將中斷處理程式分為上半部(top half)和下半部(bottom half)。上半部分任務比較少,處理一些暫存器操作、時間敏感任務,以及“登記中斷”通知核心及時處理下半部的任務。下半部分,則負責處理中斷任務中的大部分工作,如一個匯流排通訊系統中資料處理部分。

Linux中斷上下部分區別:

1)上半部由外設中斷觸發,下半部由上半部觸發。
2)上半部不會被其他中斷打斷,下半部是可以被打斷的。
3)上半部分處理任務要快,主要任務、耗時任務放在下半部。

  一般來說,在中斷上半部執行完畢,下半部即在核心的排程下被執行,當然如果有其他更高優先順序需處理的任務,會先處理該任務再排程處理下半部,或者在系統空閒時間進行處理。

Linux中斷設計
  對於Linux系統裝置而言,一個完整的中斷程式由上半部和下半部分共同構成,在編寫裝置驅動程式前,就需考慮好上半部和下半部的分配。很多時候上半部與下半部並沒有嚴格的區分界限,主要由程式設計師根據實際設計,如某些外設中斷可以沒有下半部。關於上下半部的劃分原則,就是主要事務、耗時事務劃分在下半部處理。

關於中斷上下部分的設計,可以參考以下原則:
1)與硬體相關的操作,如操作暫存器,必須放在上半部。
2)對時間敏感、要求實時性的任務放在上半部。
3)該任務不能被其他中斷或者程序打斷的放在上半部。
4)實時性要求不高的任務、耗時任務放在下半部。

Linux中斷下半部實現

  Linux下半部實現,通過核心版本更新中實現下衍化,最原始的實現手段是BH(bottom half)後在2.5版本移除,在2.3版本引入軟中斷(softirq)和tasklet機制,在2.5版本引入工作佇列(work queue在)。因此,目前使用方式是三種,軟中斷、tasklet機制、工作佇列。