device

    技术2022-05-19  33

    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为止


    最新回复(0)