關於驅動模塊自動創建設備節點

驅動模塊設備節點的自動創建,不再需要 mknod.


背景.

Linux 2.6 引入了動態設備管理, 用 udev 作爲設備管理器(應用在x86), 相比之前的靜態設備管理,在使用上更加方便靈活。
udev 根據 sysfs 系統提供的設備信息實現對/dev目錄下設備節點的動態管理,包括設備節點的創建、刪除等

引入 udev 自動創建設備節點後,比如在我們使用的 insmod led_drv.ko 時候,udev 自動幫我們在 /dev 目錄下創建設備節點;
使用 rmmod led_drv 時候,udev 自動幫我們在 /dev 目錄下刪除設備節點;
這裏並不需要我們再人爲的mknod /dev/led_dev c 239 0 來生成爲該設備在/dev目錄下創建設備文件了。

如要編寫一個能夠使用 udev 管理的設備驅動,需要在驅動代碼中調用 class_create() 爲設備創建一個 class 類 ,再調用 device_create() 爲每個設備創建對應的設備即可,從此告別需要繁瑣的 mknod ....

根據源碼解析.

設備類的申請等都在初始化函數中完成,故取前面的led_dev.c代碼中的初始化函數來解析


static struct class  *led_class;
static struct device *led_dev_device;

    ...
    ...
    ...

//入口函數
static int __init gec6818_led_init(void)
{
    int ret = 0;
	ret=alloc_chrdev_region(&led_dev_num,0,1,"myled");    //動態申請設備號,這裏的“myled”相當於代號,並不重要
    if (ret < 0)
    {
        printk("<3>""register chrdev region error\n");
        return -1;
    }
    
    //字符設備的初始化 void cdev_init(struct cdev *cdev, const struct file_operations *fops)
    cdev_init(&led_cdev, &led_fops);
    //將設備加入到內核 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
    ret = cdev_add(&led_cdev, led_dev_num, 1);
    if(ret < 0)
    {
        printk("<3>""cdev_add error\n");
        goto err_cdev_add;

    }

    led_class=class_create(THIS_MODULE, "myled");   //這裏的“myled”會顯示在/sys/class目錄當中

	if (IS_ERR(led_class))                  //判斷當前指針是否爲錯誤碼指針,大於0爲錯誤碼指針
	{
		ret = PTR_ERR(led_class);           //將指針轉爲錯誤碼
		
		printk("class_create led device fail\n");
		
		goto err_class_create;
		
	}

    led_dev_device = device_create(led_class, NULL, led_dev_num, NULL, "myled");//這裏的“myled”是設備的名字,如果創建成功,就可以在/dev目錄看到該設備的名字
    if (IS_ERR(led_dev_device))                 //創建設備失敗
    {
        ret = PTR_ERR(led_dev_device);

        printk("device_create led fail\n");
        goto err_device_create;
    }

    printk("<3>""device num: %d\n", MAJOR(led_dev_num));
    printk("<3>""device last num: %d\n", MINOR(led_dev_num));

	return 0;


err_device_create:
    class_destroy(led_class);                   //創建led類失敗,釋放內存資源

err_class_create:
    cdev_del(&led_cdev);                        //從系統刪除字符設備

err_cdev_add:
    unregister_chrdev_region(led_dev_num, 1);   //註銷設備號

    return ret;
}


類的創建 class_create() 頭文件: #include <linux/device.h>函數解析.

代碼原型:
class_create()

參數 作用
owner class的所有者,默認寫THIS_MODULE
name 自定義class的名字,會顯示在/sys/class目錄當中
返回值 成功:就返回創建好的class指針,失敗:就返回錯誤碼指針

設備的創建 device_create() 頭文件: #include <linux/device.h>

代碼原型:
device_create()

參數 作用
class 創建device是屬於哪個類
parent 默認爲NULL
devt 設備號,設備號必須正確,因爲這個函數會在/dev目錄下幫我們自動創建設備文件
drvdata 默認爲NULL
fmt 設備的名字,如果創建成功,就可以在/dev目錄看到該設備的名字
返回值 成功:就返回創建好的設備指針,失敗:就返回錯誤碼指針

類的銷燬 class_destroy() 頭文件: #include <linux/device.h>

代碼原型:
class_destroy()

參數 作用
class 創建device是屬於哪個類

設備的銷燬 device_destroy() 頭文件: #include <linux/device.h>

代碼原型:
device_destroy()

參數 作用
class 創建device是屬於哪個類
devt 設備號

錯誤碼.

錯誤碼指針的判斷

static inline long __must_check IS_ERR(const void *ptr)
{
	return IS_ERR_VALUE((unsigned long)ptr);
}


將錯誤碼指針轉換爲數值(即錯誤碼)

static inline long __must_check PTR_ERR(const void *ptr)
{
	return (long) ptr; 
}

 


我的GITHUB

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