• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > 在驅動模塊初始化函數中實現設備節點的自動創建

    在驅動模塊初始化函數中實現設備節點的自動創建

    作者: 時間:2012-08-15 來源:網絡 收藏

    我們在剛開始寫Linux程序的時候,很多時候都是利用mknod命令手動,實際上Linux內核為我們提供了一組,可以用來在加載的時候在/dev目錄下相應,并在卸載時刪除該,當然前提條件是用戶空間移植了udev。

    本文引用地址:http://www.czjhyjcfj.com/article/148609.htm

    內核中定義了STruct class結構體,顧名思義,一個struct class結構體類型變量對應一個類,內核同時提供了class_create(…),可以用它來一個類,這個類存放于sysfs下面,一旦創建好了這個類,再調用device_create(…)來在/dev目錄下創建相應的設備節點。這樣,加載的時候,用戶空間中的udev會響應device_create(…)函數,去/sysfs下尋找對應的類從而創建設備節點。

    注意,在2.6較早的內核版本中,device_create(…)函數名稱不同,是class_device_create(…),所以在新的內核中編譯以前的模塊程序有時會報錯,就是因為函數名稱不同,而且里面的參數設置也有一些變化。

    struct class和device_create(…) 以及device_create(…)都定義在/include/linux/device.h中,使用的時候一定要包含這個頭文件,否則編譯器會報錯。

    在2.6.26.6內核版本中,struct class定義在頭文件include/linux/device.h中:

    /*

    * device classes

    */

    struct class {

    coNSt char *name;

    struct module *owner;

    nbsp;struct kset subsys;

    struct list_head devices;

    struct list_head interfaces;

    struct kset class_dirs;

    struct semaphore sem; /* locks children, devices, interfaces */

    struct class_attribute *class_attrs;

    struct device_attribute *dev_attrs;

    int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);

    void (*class_release)(struct class *class);

    void (*dev_release)(struct device *dev);

    int (*suspend)(struct device *dev, pm_message_t state);

    int (*resume)(struct device *dev);

    };

    class_create(…)在/drivers/base/class.c中

    /**

    * class_create - create a struct class structure

    * @owner: pointer to the module that is to own this struct class

    * @nAME: pointer to a string for the name of this class.

    *

    * This is used to create a struct class pointer that can then be used

    * in calls to device_create().

    *

    * Note, the pointer created here is to be destroyed when finished by

    * making a call to class_destroy().

    */

    struct class *class_create(struct module *owner, cONst char *name)

    {

    struct class *cls;

    int retval;

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

    if (!cls) {

    retval = -ENOMEM;

    goto error;

    }

    cls->name = name;

    cls->owner = owner;

    cls->class_release = class_create_release;

    retval = class_register(cls);

    if (retval)

    goto Error;

    return cls;

    error:

    kfree(cls);

    return ERR_PTR(retval);

    }

    第一個參數指定類的所有者是哪個模塊,第二個參數指定類名。

    在class.c中,還定義了class_destroy(…)函數,用于在模塊卸載時刪除類。

    device_create(…)函數在/drivers/base/core.c中

    /**

    * 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

    * @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, const char *fmt, ...)

    {

    va_list vargs;

    struct device *dev;

    va_start(vargs, fmt);

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

    va_end(vargs);

    return dev;

    }

    第一個參數指定所要創建的設備所從屬的類,第二個參數是這個設備的父設備,如果沒有就指定為NULL,第三個參數是設備號,第四個參數是設備名稱,第五個參數是從設備號。

    下面以一個簡單字符設備來展示如何使用這幾個函數

    #include

    #include

    #include

    #include

    #include

    #include

    MODULE_LICENSE (GPL);

    int hello_major = 555;

    int hello_minor = 0;

    int number_of_devices = 1;

    struct cdev cdev;

    dev_t dev = 0;

    struct file_operations hello_fops = {

    .owner = THIS_MODULE

    };

    static void char_reg_setup_cdev (void)

    {

    int error, devno = MKDEV (hello_major, hello_minor);

    cdev_init (cdev, hello_fops);

    cdev.owner = THIS_MODULE;

    cdev.ops = hello_fops;

    error = cdev_add (cdev, devno , 1);

    if (error)

    printk (KERN_NOTICE Error %d adding char_reg_setup_cdev, error);

    }

    struct class *my_class;

    static int __init hello_2_init (void)

    {

    int result;

    dev = MKDEV (hello_major, hello_minor);

    result = register_chrdev_region (dev, number_of_devices, hello);

    if (result0) {

    printk (KERN_WARNING hello: can't get major number %dn, hello_major);

    return result;

    }

    char_reg_setup_cdev ();

    /* create your own class under /sysfs */

    my_class = class_create(THIS_MODULE, my_class);

    if(IS_ERR(my_class))

    {

    printk(Err: failed in creating class.n);

    return -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 );

    printk (KERN_INFO Registered character drivern);

    return 0;

    }

    static void __exit hello_2_exit (void)

    {

    dev_t devno = MKDEV (hello_major, hello_minor);

    cdev_del (cdev);

    device_destroy(my_class, MKDEV(adc_major, 0)); //delete device node under /dev

    class_destroy(my_class); //delete class created by us

    unregister_chrdev_region (devno, number_of_devices);

    printk (KERN_INFO char driver cleaned upn);

    }

    module_init (hello_2_init);

    module_exit (hello_2_exit);

    這樣,模塊加載后,就能在/dev目錄下找到hello0這個設備節點了。



    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 农安县| 南康市| 获嘉县| 兴海县| 汉源县| 微博| 广平县| 桐梓县| 富民县| 凌云县| 青州市| 克东县| 安福县| 澳门| 宿迁市| 高清| 老河口市| 无锡市| 保德县| 拜城县| 恭城| 大邑县| 九台市| 江山市| 徐州市| 哈密市| 晋江市| 新邵县| 万山特区| 宾阳县| 东源县| 定西市| 石渠县| 长阳| 普兰县| 安阳市| 阜新| 沅江市| 河曲县| 彭州市| 曲周县|