linux设备驱动模型里两个重要的数据结构:class和class_device
来源:互联网 发布:淘宝客服工作自我介绍 编辑:程序博客网 时间:2024/06/05 19:16
/************************基于linux-2.6.24.7版本内核********************************/
1、class
一个类是一个设备的高层视图,它抽象掉了底层的实现细节。例如,在驱动层面时,你可能会见到SCSI磁盘或者ATA磁盘;但在类层面时,它们都是磁盘。类允许用户空间基于它们做什么来使用设备,而不是它们如何被连接或者它们如何工作。
class表示一类设备,所有class都属于class_subsys(class子系统),即出现在/sys/class目录下,除了块设备(可能出现在/sys/block/或/sys/class/block)。
/* class结构体 */
struct class {
const char * name; /* class的名称 */
struct module * owner; /* 拥有该class的模块 */
struct kset subsys; /* 该class对应的子系统 */
struct list_head children; /* 该class的class_device列表 */
struct list_head devices;
struct list_head interfaces;
struct kset class_dirs;
struct semaphore sem; /* locks both the children and interfaces lists */
struct class_attribute * class_attrs; /* 该class的默认属性,以NULL结尾 */
struct class_device_attribute * class_dev_attrs; /* 添加到class的class_device所拥有的默认属性 */
struct device_attribute * dev_attrs;
/* 该函数提供在产生热插拔class_device事件时,添加环境变量的能力 */
int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);
/* 该函数提供在产生热插拔device(物理设备)事件时,添加环境变量的能力 */
int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
/* 添加到class的class_device移除时,调用该函数进行必要的清理工作 */
void (*release)(struct class_device *dev);
/* class被移除时,调用该函数进行必要的清理工作 */
void (*class_release)(struct class *class);
void (*dev_release)(struct device *dev);
int (*suspend)(struct device *, pm_message_t state);
int (*resume)(struct device *);
};
/* class注册函数 */
int __must_check class_register(struct class *);
void class_unregister(struct class *);
建立一个class有两种方法
a、根据需要,填充一个struct class,然后再调用class_register注册该class就ok了(此法比较灵活,可以自己定制很多东西)
b、就是通过下面的class_create来创建一个class,该函数会返回一个指向刚建立的class的指针(创建class的最简单方法)
/* class_create用于创建一个名为name的class,其owner参数一般为THIS_MODULE。class_create内部调用了class_register */
struct class *class_create(struct module *owner, const char *name);
/* class_destroy用于删除一个class,实际上其内部只是简单调用了class_unregister(cls)来注销cls */
void class_destroy(struct class *cls);
一个class属性对应于/sys/class/class.name(class.name就是该class的名称)目录里的一个文件。通过这些文件,可以向用户空间输出一些关于该class的信息,也可从用户空间获取到一些信息。
/* class属性结构体 */
struct class_attribute {
struct attribute attr;
/* 当用户空间读取该属性时,调用show函数输出一个"属性值"给用户空间 */
ssize_t (*show)(struct class *, char * buf);
/* 当用户空间写该属性时,调用store函数保存用户写入的"属性值" */
ssize_t (*store)(struct class *, const char * buf, size_t count);
};
struct attribute {
const char * name;
struct module * owner;
mode_t mode;
};
/* CLASS_ATTR可以在编译时创建一个class属性,该属性的名称为class_attr_name */
#define CLASS_ATTR(_name,_mode,_show,_store) \
struct class_attribute class_attr_##_name = __ATTR(_name,_mode,_show,_store)
/* class_create_file与class_remove_file用于创建与删除class默认属性外的属性 */
int __must_check class_create_file(struct class *,
const struct class_attribute *);
void class_remove_file(struct class *, const struct class_attribute *);
2、class_device
一个class可以看成是一个容器(一个子系统subsystem),包含了很多的class_device,这些class_device是由class这个大的容器来管理的,而每个class_device都对应着一个具体的设备。
每个class对象包括一个class_device链表,每个class_device对象表示一个逻辑设备并通过struct class_device中的dev成员(一个指向struct device的指针)关联一个物理设备。一个逻辑设备总是对应一个物理设备,而一个物理设备却可以对应多个逻辑设备。
实际上,class_device在/sys/class/subsystem生成的目录就是上面提到的class_device。这样第2点也有了。
/* class_device结构体 */
struct class_device {
struct list_head node; /* 仅供驱动核心内部使用 */
struct kobject kobj; /* 该class_device相应的kobject,仅供驱动核心内部使用 */
struct class * class; /* 该class_device所属的class,必须有 */
dev_t devt; /* 该class_device的设备编号,用于创建其dev属性文件,仅供驱动核心内部使用 */
struct device * dev; /* 指向该class_device相关的device结构体(物理设备),可选.若不为NULL,用于创建一个从class入口到/sys/devices下相应入口的符号连接,以便用户空间查找设备入口 */
void * class_data; /* 该class_device的私有数据指针 */
struct class_device *parent; /* parent of this child device, if there is one */
struct attribute_group ** groups; /* optional groups */
void (*release)(struct class_device *dev);
int (*uevent)(struct class_device *dev, struct kobj_uevent_env *env);
char class_id[BUS_ID_SIZE]; /* 该class_device的名称,在其所属class中应是唯一的,不可重名 */
};
/* class_devic注册函数 */
int __must_check class_device_register(struct class_device *);
void class_device_unregister(struct class_device *);
与class一样,建立一个class_device也有两种方法
a、根据需要,填充一个struct class_device,然后再调用class_device_register注册该class_device就ok了(此法比较灵活,可以自己定制很多东西)
b、就是通过下面的class_device_create来创建一个class_device,该函数会返回一个指向刚建立的class_device的指针(创建class_device的最简单方法)
/* class_device_create用于创建一个class_device,其名称最后两个参数决定(类似于printf的格式化字符串)
* cls指明了其所属的class,可以是自己填充的class或由class_create返回的class
* parent指明了该class_device的父class_device,若没有,则为NULL
* 该class_device的设备编号,用于创建其dev属性文件,必须指明
* device指明了该class_device(逻辑设备)对应的device(物理设备),可有可无,无则为NULL
* 实际上,class_device_create也就是填充一个class_device,然后调用了class_device_register注册该class_device
*/
struct class_device *class_device_create(struct class *cls,
struct class_device *parent,
dev_t devt,
struct device *device,
const char *fmt, ...)
__attribute__((format(printf,5,6)));
/* class_destroy用于删除一个class,内部调用了class_unregister(cls)来注销cls */
void class_device_destroy(struct class *cls, dev_t devt);
class_device属性对应于/sys/class/class.name/class_device.class_id目录下一个文件。通过这些文件,可以向用户空间输出一些关于该class_device的信息,也可从用户空间获取到一些信息。
/* class_device属性,其show和store函数类似于class属性的show和store函数 */
struct class_device_attribute {
struct attribute attr;
ssize_t (*show)(struct class_device *, char * buf);
ssize_t (*store)(struct class_device *, const char * buf, size_t count);
};
/* CLASS_DEVICE_ATTR可以在编译时创建一个class_device属性,该属性的名称为class_device_attr_name */
#define CLASS_DEVICE_ATTR(_name,_mode,_show,_store) \
struct class_device_attribute class_device_attr_##_name = \
__ATTR(_name,_mode,_show,_store)
/* class_device_create_file与class_device_remove_file用于创建与删除class_device默认属性外的属性 */
int __must_check class_device_create_file(struct class_device *,
const struct class_device_attribute *);
void class_device_remove_file(struct class_device * class_dev,
const struct class_device_attribute * attr);
其实,在调用class_device_register注册一个class_device时,该函数内部调用了
int class_device_add(struct class_device *class_dev)
在class_device_add内,通过class_device_create_file创建dev、uevent和该class_device所拥有的默认属性(由class_device.class->class_dev_attrs指定)等属性文件。这样第3点也有了。
dev属性文件用于向用户空间输出该class_device的设备编号。
uevent属性文件使用户可以手动触发uevent事件(通过向该文件写,如add、remove等字符串)。
- linux设备驱动模型里两个重要的数据结构:class和class_device
- linux设备驱动中重要的3个数据结构 &&Linux设备驱动模型几个基本数据结构模型:kobject,kset,subsystem
- linux设备驱动模型--class
- linux设备驱动中重要的3个数据结构
- 44 linux内核里的platform设备驱动模型
- 67 linux内核里的framebuffer设备驱动模型
- linux设备驱动模型十之class
- LINUX设备驱动模型之class
- linux设备驱动模型之class
- Linux设备驱动模型之底层数据结构
- Linux设备驱动模型之底层数据结构
- Linux设备驱动模型之底层数据结构
- linux 设备驱动模型 class 设备结点文件 热插拔
- Linux Kernel设备驱动模型之class迭代设备
- Linux Kernel设备驱动模型之class 查找设备
- 基于mdev(udev)的驱动架构与linux设备驱动模型之class
- 基于mdev(udev)的驱动架构与linux设备驱动模型之class
- linux文件系统的系统分析--(十五)sysfs和设备模型--Class
- IOS开发(37)之iphone开发中的delegate
- 一懒到底——轻松注册Exe程序为Windows系统服务
- struts2 s标签
- When to use comparable and comparator interfaces in java
- iOS平台内存常见问题
- linux设备驱动模型里两个重要的数据结构:class和class_device
- 轻松掌握ISO8583报文协议
- 杀人后一个孩子的做法…不看你会后悔的…
- oracle-instantclient 配置
- 使用DirectSound时,常用到的CWaveFile类
- Asp.Net中global.asax文件的描述
- 均衡器的文章
- MYSQL删除表的记录后如何使ID从1开始
- 解析 Java 类和对象的初始化过程