zoukankan      html  css  js  c++  java
  • device_create函数分析 【一】

    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 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);
    
    这是前文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为止
    


  • 相关阅读:
    10-JavaScript 条件语句
    9-JavaScript 比较
    8-JavaScript 运算符
    6-JavaScript 事件
    Sum Problem 重定向文件的使用
    Calculate A + B.
    Vue中computed的本质及与methods的区别
    外部文件使用django的models
    DjangoURL反向解析
    字符串格式化的方式
  • 原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124330.html
Copyright © 2011-2022 走看看