Linux 驅動程式的中斷處理, #2: 深入淺出中斷模式

jollen 發表於 March 2, 2008 10:09 PM

Interrupt handler 的工作是負責處理裝置的中斷請求,並將結果回報(feedback)給裝置。一般而言,裝置產生中斷時,都是與資料讀寫有關的請求。Interrupt handler 便要根據中斷的特性,來判斷此中斷是要請求驅動程式將資料寫入至裝置,或是由裝置讀取資料。

Linux 驅動程式的 interrupt handler 實作原則如下:

1. 在 interrupt handler 裡,叫醒真正負責此中斷的 task 後立即結束執行。
2. Interrupt handler 應儘量執行最少的程式碼。
3. Interrupt handler 若執行過久,會造成中斷的關閉時間過長,因此可能會遺失緊接著產生的中斷請求。
4. 若 interrupt handler 裡有過長的計算動作或執行過久的程式碼,則應使用 tasklet 或 task queue 將該段程式碼做排程,留待其它時間再執行。如此便可避免interrupt handler執行時間過久。

此外,在中斷模式下做同步控制時,還要考慮是否會佔用過久 CPU 時間的問題。為什麼中斷模式下寫 code 需要注意這個議題呢?請看以下的說明。

Counting Semaphore

在作業系統教科書中,提及二種 semaphore 的做法:

1. blocking counting semaphore,即 Linux 的 down/up 版本。
2. spinlock counting semaphore,即 Linux 的 spinlock。

Spinlock counting semaphore 屬於傳統作法,spinlock 讓 waiting 的動作(P operation)以 busy-loop 方式實作,因此會佔用 CPU 資源;blocking counting semaphore 則是將 waiting 的動作以 blocking(sleeping) 的方式來進行。

在Linux kernel 裡,blocking counting semaphore 採用 wait queue 來實作,即以 sleep 方式做P operation。Wait queue 機制對驅動程式來說,原始用意為實作 process(user-space)的 blocking read 與 blocking write,這樣的 behavior 機制經常出現在實作 process 讀取裝置資料的場合;當 process 進行 blocking I/O 讀寫(synchronous I/O)時,由於 kernel-space 是以 sleeping 方式進行等待,因此能把 CPU 交給其它人使用,並將 process 排程到 I/O queue(waiting queue),因此不獨佔或浪費 CPU 時間。

在中斷模式下,因為不能使用 sleeping 版本的 semaphore,所以必須使用 spinlock,在此情況下,便會遭遇到 interrupt handler 佔用 CPU 時間太久的問題。

Jollen's Blog 使用 Github issues 與讀者交流討論。請點擊上方的文章專屬 issue,或 open a new issue

您可透過電子郵件 jollen@jollen.org,或是 Linkedin 與我連絡。更歡迎使用微信,請搜尋 WeChat ID:jollentw