device_create分析

device_create分析
2010-11-12 10:46

2.6比較新的內核裏面,這個函數在設備驅動中比較重要,拿出來單獨分析下

源碼如下:

/**

* device_create - creates a device and registers it with sysfs

* @class: pointer to the struct class that this device should be registered to

* @parent: pointer to the parent struct device of this new device, if any

* @devt: the dev_t for the char device to be added

* @drvdata: the data to be added to the device for callbacks

* @fmt: string for the device's name

*

* This function can be used by char device classes. A struct device

* will be created in sysfs, registered to the specified class.

*

* A "dev" file will be created, showing the dev_t for the device, if

* the dev_t is not 0,0.

* If a pointer to a parent struct device is passed in, the newly created

* struct device will be a child of that device in sysfs.

* The pointer to the struct device will be returned from the call.

* Any further sysfs files that might be required can be created using this

* pointer.

*

* Note: the struct class passed to this function must have previously

* been created with a call to class_create().

*/

struct device *device_create(struct class *class, struct device *parent,

                          dev_t devt, void *drvdata, const char *fmt, ...)

{

       va_list vargs;

       struct device *dev;

       va_start(vargs, fmt);

       dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);

       va_end(vargs);

       return dev;

}

先看參數

@class: pointer to the struct class that this device should be registered to

the struct class 指針,必須在本函數調用之前先被創建

parent: pointer to the parent struct device of this new device

該設備的parent指針。

devt: the dev_t for the char device to be added

字符設備的設備號,如果dev_t不是0,0的話,1”dev”文件將被創建。

drvdata: the data to be added to the device for callbacks

被添加到該設備回調的數據。

fmt: string for the device's name

設備名字。

可以看下面的函數調用例子

例子1

/* register your own device in sysfs, and this will cause udev to create corresponding device node */

   device_create( my_class, NULL, MKDEV(hello_major, 0), "hello" "%d", 0 );

如果成功,它將會在/dev目錄下產生/dev/hello0設備。

例子2

led_cdev->dev = device_create_drvdata(leds_class, parent, 0, led_cdev,

                                         "%s", led_cdev->name);

這是前文platformgpio-leds裏面的源碼

由於dev_t0,所以它不會在/dev下產生設備文件。

led_cdev爲傳遞給class的私有數據。

會把第6個參數的內容複製到第5個參數 “%s”,就像printf一樣。

通過這2個例子,應該對它的用法有所瞭解了,下面看下源碼。

dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);

深入device_create_vargs

/**

* device_create_vargs - creates a device and registers it with sysfs

* @class: pointer to the struct class that this device should be registered to

* @parent: pointer to the parent struct device of this new device, if any

* @devt: the dev_t for the char device to be added

* @drvdata: the data to be added to the device for callbacks

* @fmt: string for the device's name

* @args: va_list for the device's name

*

* This function can be used by char device classes. A struct device

* will be created in sysfs, registered to the specified class.

*

* A "dev" file will be created, showing the dev_t for the device, if

* the dev_t is not 0,0.

* If a pointer to a parent struct device is passed in, the newly created

* struct device will be a child of that device in sysfs.

* The pointer to the struct device will be returned from the call.

* Any further sysfs files that might be required can be created using this

* pointer.

*

* Note: the struct class passed to this function must have previously

* been created with a call to class_create().

*/

struct device *device_create_vargs(struct class *class, struct device *parent,

                               dev_t devt, void *drvdata, const char *fmt,

                               va_list args)

{

       struct device *dev = NULL;

       int retval = -ENODEV;

       if (class == NULL || IS_ERR(class))

              goto error;

       dev = kzalloc(sizeof(*dev), GFP_KERNEL);

       if (!dev) {

              retval = -ENOMEM;

              goto error;

       }

       dev->devt = devt;

       dev->class = class;

       dev->parent = parent;

       dev->release = device_create_release;

       dev_set_drvdata(dev, drvdata);

       vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);

       retval = device_register(dev);

       if (retval)

              goto error;

       return dev;

error:

       kfree(dev);

       return ERR_PTR(retval);

}

代碼比較容易,最靈活的在這個地方

vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);

vsnprintf()會根據參數fmt字符串來轉換並格式化數據,然後將結果複製到數組dev->bus_id所指的字符串數組,知道出現字符串結束符或達到參數BUS_ID_SIZE爲止

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