【轉】Linux驅動修煉之道-按鍵

按鍵程序使用了驅動的很多知識。有中斷,阻塞,等待隊列,linux設備驅動模型等。
使用中斷處理的步驟是:

  1. 向內核註冊中斷
  2. 實現中斷處理函數。

安裝中斷的函數是:

釋放的函數:

這裏主要是申請中斷信號線,這是一個非常寶貴的資源。request_irq中的參數dev_id用於共享中斷信號線的時候,因爲需要中斷處理的設備肯定比中斷信號線多的,所以一旦某一個觸發了中斷,內核需要在這條中斷線上尋找發生中斷的設備,由於大家使用的中斷號是一樣的,所以通過dev_id來識別,dev_id是唯一的。使用完要注意釋放着寶貴的資源。從下邊的程序可以看到註冊中斷是在open的時候,爲什麼不在註冊模塊的函數中呢,因爲如果是在註冊函數中除非卸載模塊,這樣這個驅動會一直佔用中斷號,而自己可能不用,這樣就白白浪費了寶貴的資源。
中斷處理的函數原型是:

第一個參數是irq,第二個是dev_id,第三個是struct pt_reg *regs,很少用,它保存了處理器進入中斷代碼之前的處理器上下文快照。注意返回值,如果處理程序發現其設備的確需要處理,則應返回IRQ_HANDLED;否則,返回值應該是IRQ_NONE。

在讀取的時候使用的是阻塞機制,也就是說如果用戶程序獲得不到數據,就阻塞。此時那個進程進入休眠狀態,被CPU的調度器從運行隊列搬到等待隊列。Linux內核中阻塞是通過等待隊列來實現的。在Linux中,一個等待隊列通過一個“等待隊列頭(wait queue head)”來管理。等待隊列頭是一個類型爲wait_queue_head_t的結構體,定義在<linux/wait.h>中。

可通過如下方法靜態定義並初始化一個等待隊列:

或者用動態的方法:

 

 

Linux內核中的休眠方式是使用wait_event宏,如下:

 

 

queue是等待隊列頭,condition是等待條件。如果condition爲0,則進行阻塞;否則,不阻塞。wait_event_interruptible宏與wait_event宏的區別是wait_event_interruptible是可以被信號中斷的。當進程休眠時,它將期待某個條件在未來成爲真;當一個進程被喚醒時,它必須再次檢測它所等待的條件的確爲真。
用來喚醒等待隊列的函數:

 

 

wake_up會喚醒等待在給定queue上的所有進程。wake_up_interruptible只會喚醒那些執行可中斷休眠的進程。

 

 

用戶測試程序:

Makefile:

效果:

觀察效果圖,有的時候是按1次,有的是2,3,7等,看看用戶程序,那裏一直在讀,如果按鍵不按下,則沒有任何輸出,因爲讀取進程被阻塞了,如果按下在讀後按的次數會被清零。那應該都顯示1啊,因爲驅動程序中每按一次,在中斷程序中喚醒等待進程,然後讀取函數中進行了清零,應該每次都爲1。可是,進程被喚醒後從等待隊列搬到運行隊列,在運行隊列需要排隊的,也就是說,可能不會立即獲得時間片,這樣下次中斷又進行了加1,所以。。。哈哈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章