02 關於裝置號,裝置節點等一些簡單概念
2,裝置號 裝置號分為主裝置號和次裝置號; 主裝置號標識裝置對應的驅動程式,次裝置號由核心使用,區分同一個型別的多個裝置,如兩個串列埠。個人認為了解這些就夠了。我們需要重點關注的是驅動程式裡面如何表達這些概念,也就是下一步。 dev_t devno //定義裝置號,資料型別為dev_t,實際是一個32位的數。 devno = MKDEV(int major, int minor); //major minor 即我們看到的程式設計師給出的203,0等這些數字。習慣上限於255個主裝置號,255個次裝置號 devno = major << 20 | minor; int major = MAJOR(dev_t devno); int minor = MINOR(dev_t devno); //與上面的相反,如果你想通過dev_t devno獲得主裝置號和次裝置號的話,可以這麼做。 3,分配和釋放裝置號
直接上程式碼 #include <linux/fs.h> int register_chrdev_region(dev_t first, unsigned int count, char *name); void unregister_chrdev_region(dev_t first, unsigned int count); int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name); 引數說明: dev_t first :MKDEV();獲取得到的裝置號, unsigned int count :連續裝置編號的個數 char *name :檔案系統中看到的裝置驅動的名稱,cat /proc/devices 或 ls /dev/下能看到的 初始化時需要register,退出時需要unregister。 alloc顧名思義,動態分配。經常認為通用PC隨機分配,嵌入式產品需提前規劃好,故儘量用靜態。 register成功返回0,失敗返回負的錯誤碼,時刻謹記,可能失敗,所以要新增if判斷。 驅動程式設計師們經常這樣寫:
4,裝置節點 當你驅動程式按上面的步驟寫好後,編譯並且insmod。你會發現檔案系統中: cat /proc/devices/下會出現你新增的裝置名稱,和主裝置號。但是/dev/下並沒有存在你所註冊的dev。這是因為你還沒有建立裝置節點。這時你需要執行如下命令: mknod /dev/name c $major minor 你可以確定count 個裝置節點,根據你程式碼中register時指定的count個數。 動態分配主裝置號有一個缺點:無法預先建立裝置節點。不過,你可以通過/proc/devices/中獲得。如果要寫成指令碼自動分配,可以參考書Page 51,有一個很棒的shell指令碼,幫我們完成了。 最後附上幾行簡單的完整的註冊裝置號程式: 1 #include <linux/module.h> 2 #include <linux/init.h> 3 #include <linux/kernel.h> 4 #include <linux/fs.h> //note: register_chrdev need it 5 6 MODULE_LICENSE("Dual BSD/GPL"); 7 8 static int __init scull_init(void) 9 { 10 dev_t devno = MKDEV(250, 66); 11 int ret; 12 13 printk(KERN_ALERT "scull dev init\n"); 14 ret = register_chrdev_region(devno, 3, "scull"); 15 if (0 == ret ) { 16 printk(KERN_ALERT " register success\n"); 17 } else { 18 printk(KERN_ALERT "register fail ret:%d\n", ret); 19 goto register_fail; 20 } 21 22 return 0; 23 register_fail: 24 unregister_chrdev_region(devno, 1); 25 } 26 static void __exit scull_exit(void) 27 { 28 dev_t devno = MKDEV(250, 66); 29 30 printk(KERN_ALERT "scull exit\n"); 31 unregister_chrdev_region(devno, 1); 32 } 33 34 module_init(scull_init); 35 module_exit(scull_exit);