2021-07-06
關鍵字:主設備號、次設備號
1、什麼是設備號
設備號是Linux驅動開發中的術語。
Linux規定每一個字符設備或塊設備都必須擁有一個專屬設備號。要想在Linux平臺開發驅動程序,申請設備號就是開發過程的第一步,只有有了設備號,才能向系統註冊設備。
一個設備號由以下兩個模塊組成:
1、主設備號;
2、次設備號;
主設備號用以表示一個驅動程序的種類。如:USB、顯示器、鼠標等。
次設備號用以表示此種類下具體的設備。如:第n個USB接口、第n個顯示屏、第n個鼠標等。
主設備號是抽象的事物種類,次設備號則是具象的實體設備。
在 /proc/devices 文件中記載着系統中所有已註冊的主設備號及其註冊名稱。
設備號佔32位的寬度。其中主設備號佔高12位,次設備號佔低20位。不過雖然主設備號的寬度長達12位,實際上在Linux系統中有效值範圍僅爲 1 ~ 255。
2、設備號相關的接口
雖然我們知道主設備號和次設備號的具體位置,但是還是應該以系統提供的接口來拆分和組合主次設備號。
在Linux內核中,設備號被描述爲 dev_t 類型,如下所示:
typedef u_long dev_t;
這個類型的定義隱藏的很深,不必去糾結它的實際定義頭文件。我們在開發驅動過程中只需要引入kdev_t.h頭文件就可以使用此類型的了:
./kernel/include/linux/kdev_t.h
同時,kdev_t.h頭文件中還定義了拆分和組合主次設備號的宏,簡要概括如下:
MAJOR(dev_t) //從設備號中將主設備號拆分出來 MINOR(dev_t) //從設備號中將次設備號拆分出來 MKDEV(major, minor) //將主設備號和次設備號組合成設備號
3、靜態註冊
第1節有提到過:必須持有設備號才能向系統註冊設備。而設備號是一個整數,所以理論上我們可以隨意“捏造”一個設備號用以向系統註冊我們的設備。這種“捏造”設備號以註冊設備的形式就被稱爲“靜態註冊”方式。
不過這裏有一個前提條件:儘量不要和已有的設備號衝突,否則可能會導致設備工作不正常。一般可以在內核源碼的 documentation/devices.txt 中看到所有已被註冊使用的設備號,我們按需選擇一個沒被佔用的即可。不過如果我們要添加的設備的種類就是系統中已有的種類,那一般我們只需要註冊次設備號不要衝突就可以了。
靜態註冊的方式需要注意的點太多,徒增開發難度。因此應儘量使用動態註冊的形式。
4、動態註冊
Linux有提供一個動態分配設備號的接口,其原型如下所示:
int alloc_chrdev_region(dev_t* devid, unsigned int baseminor, unsigned int count, const char* name);
參數 devid 作爲輸出參數使用。
參數 baseminor 表示次設備號起始值。按需設置即可。
參數 count 表示要申請使用的次設備號的數量。
參數 name 表示此設備的描述名稱,即在 /proc/devices 中看到的名稱。
返回值0表示申請成功。
與動態註冊相對的是釋放接口。Linux中的設備號是交由系統託管的。如果某驅動程序在運行過程中動態申請了某設備號,但是在卸載時沒有釋放,則該設備號仍舊存活於系統中。釋放設備號的接口原型如下所示:
void unregister_chrdev_region(dev_t devid, unsigned int count);
參數 devid 表示設備號。
參數 count 即次設備號數量。