device_create函数分析 【一】

来源:互联网 发布:严重程度评估矩阵图 编辑:程序博客网 时间:2024/05/21 11:23
device_create函数分析 在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 tothe 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设备。 例子2led_cdev->dev = device_create_drvdata(leds_class, parent, 0, led_cdev,                                         "%s", led_cdev->name);这是前文platform之gpio-leds里面的源码由于dev_t是0,所以它不会在/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为止