編寫字元設備驅動程序「linux字元設備驅動流程圖」

Linux字元設備驅動框架

1. 設備號

Linux內核中有很多的字元設備驅動,內核是如何區分它們的? 每個字元設備都有一個唯一的標識 – 設備號,設備號的本質: 32位的無符號整數(dev_t)。

設備號由兩部分組成:

1 – 高12位稱為主設備號,表明這個設備屬於哪一類設備。

2 – 低20位成為次設備號,表明這個設備是同類設備中的具體哪一個。

設備號的申請方法:

第一種方法:靜態定義並註冊設備號

首先查看系統中有哪些設備號沒有被分配給具體的設備,然後確定一個給當前的設備使用(cat /proc/devices可以看哪些號被佔用了),定義方法如下:

dev_t devno = 主設備號<<20 | 次設備號;

或者使用系統介面進行組合

如何寫一個最簡單的Linux字元設備驅動?

註冊設備號 – 使申請的設備號生效並保證設備號在Linux內核中的唯一性,使用下面的介面:

如何寫一個最簡單的Linux字元設備驅動?

from: 要註冊的設備號

count:要註冊多少個設備號,例如count = 3, 主設備號是255, 次設備號是0,那麼將按照順序依次註冊三個設備號,分別是(主:255,從:0)、(255,1)、(255,2)

name:給要註冊的設備命名,註冊成功可以通過cat /proc/devices查看到

第二種方法:動態申請並註冊設備號

此方法無需自己去確定哪個設備號可用,內核會查詢哪個設備號沒有被使用,然後分配給當前驅動進行註冊,所以大部分驅動都採用這種註冊方法,使驅動更加具有通用性(如果用靜態註冊,你選的設備號在當前設備上沒有使用,但是當這個驅動移植到其他的設備上,可是其他設備上的某個驅動也使用的這個這個設備號,那麼這個驅動就會註冊失敗)。

如何寫一個最簡單的Linux字元設備驅動?

功能:申請一個或多個設備號並進行註冊

dev:要註冊的設備的設備號,輸入參數,內核會尋找沒有使用的設備號,然後填充到這個dev參數中。

baseminor:主設備號由內核來確定,次設備號由我們自己去確定,baseminor就對應要申請的設備號的次設備號。

count:可以一次申請多個設備號,count表示要申請的設備號的數量,當申請多個設備號時,他們的主設備號一致,次設備號會在baseminor的基礎上依次加1。

name:要註冊的設備的名字,註冊成功可以通過cat /proc/devices查看到

最後,無論通過哪種方式註冊的設備號,在卸載模塊的時候都需要將註冊的設備號資源進行釋放:

如何寫一個最簡單的Linux字元設備驅動?

from:要釋放的設備號

count:要一次釋放的設備號的數量,當釋放多個設備號時,系統會從from開始,依次加1作為新的設備號進行釋放

2. 字元設備操作集合 – file_operations結構體

設備驅動有各種各樣的, 滑鼠驅動需要獲取用戶的坐標以及單雙擊動作、LCD驅動需要寫framebuffer等等,但是對上層開發調用這些驅動的人來說,他們可能不懂也不關心底層設備是如何工作的,為了簡化上層應用的操作,驅動程序給上層提供了統一的操作介面–open、read、write等,這樣,對應做應用開發的人來說,不管你是什麼樣的設備,我只需要去打開(open)你這個設備,然後進行讀寫等操作就可以操作這個設備了。那麼,驅動程序如何實現這樣統一的介面呢?需要實現下面的file_operations結構體:

如何寫一個最簡單的Linux字元設備驅動?

這裡只列出了幾個最基本的成員:

owner:一般填充THIS_MODULE,表示這個驅動(模塊)歸自己所有(這個概念對於初學者可能難以理解,到後面我會繼續說明)

open:打開設備驅動的函數指針

release:關閉設備驅動的函數指針,為了對每個設備驅動的訪問保護,所以用戶必須先打開設備,才能對設備進行讀寫等操作,操作完必須再關掉。

read:讀設備驅動的函數指針(比如用戶可以通過read介面讀取按鍵驅動的按鍵狀態等)

write:寫設備驅動的函數指針(比如用戶可以通過write介面寫LCD驅動的framebuffer顯存,將畫面顯示再lcd上)

用法:

定義一個屬於自己設備的操作集合xxx_fops,xxx通常命名為設備的名字,例如lcd_fops, key_fops等。

如何寫一個最簡單的Linux字元設備驅動?

3. 字元設備的核心 – cdev結構體

分配、設置、註冊cdev結構體

內核用cdev結構體來表示一個字元設備,所以每個字元設備驅動,都需要註冊一個cdev結構體。

如何寫一個最簡單的Linux字元設備驅動?

owner:一般填充THIS_MODULE,表示這個驅動(模塊)歸自己所有。

ops:對應這個設備的文件操作集合。

list:內核中有很多字元設備,每個設備對應一個自己的cdev,這些cdev通過這個list連在一起,當註冊一個新的cdev時,就會通過cdev裡面的list掛到內核的cdev鏈表上。

count:同類設備,可以一次註冊多個cdev,但是他們的操作方法(fops)是一樣的,比如usb設備,多個usb共用一套操作方法(fops),但是每個usb都有自己的cdev。

如何寫一個最簡單的Linux字元設備驅動?

註冊cdev結構體 – 添加一個字元設備(cdev)到系統中:

如何寫一個最簡單的Linux字元設備驅動?

有註冊同樣也有釋放:

如何寫一個最簡單的Linux字元設備驅動?

最後的代碼

如何寫一個最簡單的Linux字元設備驅動?
如何寫一個最簡單的Linux字元設備驅動?
如何寫一個最簡單的Linux字元設備驅動?

Makefile:

如何寫一個最簡單的Linux字元設備驅動?

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/281166.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-21 13:16
下一篇 2024-12-21 13:16

相關推薦

發表回復

登錄後才能評論