linux驱动学习(四)自建立设备文件节点

---恢复内容开始---node

1: 首先回顾一下以前的学习内容:linux

  1:register_chrdev来注册字符设备驱动,用这种方法的好处是简单,只须要一个函数就能够注册字符设备驱动了,缺点是没法设置次设备号;app

  2:register_chrdev_region/allco_chrdev_region、cdev_XXX这些函数来配合注册设备驱动,单纯使用这些函数存在一个问题就是没法自动在/dev目录下面建立ide

驱动设备文件,咱们在嵌入式设备中通常使用busybox中的mdev来实现驱动设备文件的自动建立,可是驱动设备文件的建立须要一个uevent文件;函数

  3:uevent文件是有kobject_uevent函数来实现的;因此咱们为了设备文件的自动生成,首先使用class_create函数来建立一个设备类,在用device_create函数学习

把子目录建立了,这时候就会有一个uevent文件,而后mdev会自动的根据uevent建立/dev/目录下面的设备文件;测试

  4:因此咱们在module_init的时候要把sys目录下的类建立了,以及把device也建立了;ui

下面是详细分析:this

class_create函数:spa

class_create

  __class_create      

    __class_register

      kset_register  

        kobject_uevent

class是建立了一个类即结构体struct class,对应的是在sysfs目录下面建立了一个关于这个类的文件夹

owner:THIS_MODULE  name : leds   而后是用device_create在建立相应的设备文件;  

#define class_create(owner, name) ({ static struct lock_class_key __key; __class_create(owner, name, &__key); })

class_create实际上是一个宏,调用的是__class_create这个函数

struct class *__class_create(struct module *owner, const char *name, struct lock_class_key *key) { 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, key); if (retval) goto error; return cls; error: kfree(cls); return ERR_PTR(retval); }
struct class { const char        *name; struct module        *owner; struct class_attribute        *class_attrs; struct device_attribute        *dev_attrs; struct kobject            *dev_kobj; int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); char *(*devnode)(struct device *dev, mode_t *mode); 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); const struct kobj_ns_type_operations *ns_type; const void *(*namespace)(struct device *dev); const struct dev_pm_ops *pm; struct class_private *p; };

 

device_create

struct device *device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...)

例子:device_create(batman_class, NULL, MKDEV(tmp_major, 0), NULL, "batman-adv");

struct device { struct device        *parent; struct device_private    *p; struct kobject kobj; const char        *init_name; /* initial name of the device */
    struct device_type    *type; struct mutex        mutex;    /* mutex to synchronize calls to * its driver. */

    struct bus_type    *bus;        /* type of bus device is on */
    struct device_driver *driver;    /* which driver has allocated this device */
    void        *platform_data;    /* Platform specific data, device core doesn't touch it */
    struct dev_pm_info power; #ifdef CONFIG_NUMA int        numa_node;    /* NUMA node this device is close to */
#endif u64 *dma_mask;    /* dma mask (if dma'able device) */ u64 coherent_dma_mask;/* Like dma_mask, but for alloc_coherent mappings as not all hardware supports 64 bit addresses for consistent allocations such descriptors. */

    struct device_dma_parameters *dma_parms; struct list_head    dma_pools;    /* dma pools (if dma'ble) */

    struct dma_coherent_mem    *dma_mem; /* internal for coherent mem override */
    /* arch specific additions */
    struct dev_archdata archdata; #ifdef CONFIG_OF struct device_node    *of_node; #endif dev_t devt; /* dev_t, creates the sysfs "dev" */ spinlock_t devres_lock; struct list_head devres_head; struct klist_node knode_class; struct class        *class; const struct attribute_group **groups;    /* optional groups */

    void    (*release)(struct device *dev); };

device_create

  device_create_vargs:对device类中的变量赋值,devt name release等初始化这个结构体中的变量

     device_register : 对设备的初始化,就是把这个结构体,插入到链表中;

       device_add :建立设备文件

        device_create_file

        device_create_sys_dev_entry

        device_add_class_symlinks

        device_add_attrs

        bus_add_device

        dpm_sysfs_add

        kobject_uevent

相似的还有DRIVER_ATTR,BUS_ATTR,CLASS_ATTR。这几个东东的区别就是,DEVICE_ATTR对应的文件在/sys/devices/目录中对应的device下面。
而其余几个分别在driver,bus,class中对应的目录下。此次主要介绍DEVICE_ATTR,其余几个相似。

struct device_attribute { struct attribute attr; ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); };

 

struct attribute { const char        *name; struct module        *owner; mode_t mode; #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lock_class_key    *key; struct lock_class_key skey; #endif };

 

http://blog.csdn.net/wujiangguizhen/article/details/37929963

device_attribute的主要是由 name、owner、show、store四个元素组成;

先看看DEVICE_ATTR的原型:
DEVICE_ATTR(_name, _mode, _show, _store)
_name:名称,也就是将在sys fs中生成的文件名称。
_mode:上述文件的访问权限,与普通文件相同,UGO的格式。
_show:显示函数,cat该文件时,此函数被调用。
_store:写函数,echo内容到该文件时,此函数被调用。

 

这就是真正建立class目录下的文件的函数:

咱们看一下在i2c-0目录下有6个文件,这些文件就是用上面的那些函数生成的,有了uevent文件之后咱们在安装驱动模块的时候mdev会自动生成/dev/ 下的设备文件节点

注意:在删除模块的时候记得使用

device_destroy
class_destroy

这两个函数把建立的文件删除;

下面写代码来测试一下:

 

 

 

 

 

 

 

 

 

 

struct class这个结构体在include/linux/device.h头文件中定义的;

---恢复内容结束---

相关文章
相关标签/搜索