了解Linux设备驱动的设备模型.doc
《了解Linux设备驱动的设备模型.doc》由会员分享,可在线阅读,更多相关《了解Linux设备驱动的设备模型.doc(9页珍藏版)》请在三一文库上搜索。
1、了解Linux设备驱动的设备模型Linux设备模型是对系统设备组织架构进行抽象的一个数据结构,旨在为设备驱动进行分层、分类、组织。降低设备多样性带来的Linux驱动开发的复杂度,以及设备热拔插处理、电源管理等。Overview设计目的电源管理和系统关机(Power management and system shutdown)设备之间大多情况下有依赖、耦合,因此要实现电源管理就必须对系统的设备结构有清楚的理解,应知道先关哪个然后才能再关哪个。设计设备模型就是为了使系统可以按照正确顺序进行硬件的遍历。与用户空间的交互(Communications with user space)实现了sysfs
2、虚拟文件系统。它可以将设备模型中定义的设备属性信息等导出到用户空间,使得在用户空间可以实现对设备属性的访问及参数的更改。详见DocumentaTIon/filesystems/sysfs.txt。可热插拔设备(Hotpluggable devices)设备模型管理内核所使用的处理用户空间热插拔的机制,支持设备的动态添加与移除。设备类别(Device classes)系统的许多部分对设备如何连接没有兴趣, 但是它们需要知道什么类型的设备可用。设备模型也实现了一个给设备分类的机制, 它在一个更高的功能性级别描述了这些设备。对象生命期(Object lifecycles)设备模型的实现一套机制来处理
3、对象生命期。设备模型框图Linux 设备模型是一个复杂的数据结构。如图所示为和USB鼠标相关联的设备模型的一小部分:这个框图展示了设备模型最重要的四个部分的组织关系(在顶层容器中详解):Devices描述了设备如何连接到系统。Drivers系统中可用的驱动。Buses跟踪什么连接到每个总线,负责匹配设备与驱动。classes设备底层细节的抽象,描述了设备所提供的功能。底层实现kobject作用与目的Kobject是将整个设备模型连接在一起的基础。主要用来实现以下功能:对象的引用计数(Reference counTIng of objects)通常, 当一个内核对象被创建, 没有方法知道它会存在
4、多长时间。 一种跟踪这种对象生命周期的方法是通过引用计数。 当没有内核代码持有对给定对象的引用, 那个对象已经完成了它的有用寿命并且可以被删除。sysfs 表示(Sysfs representaTIon)在sysfs中显示的每一个项目都是通过一个与内核交互的kobject实现的。数据结构粘和(Data structure glue)设备模型整体来看是一个极端复杂的由多级组成的数据结构, kobject实现各级之间的连接粘和。热插拔事件处理(Hotplug event handling)kobject处理热插拔事件并通知用户空间。数据结构/* include in */struct kobjec
5、t const char *name; /* 该kobject的名称,同时也是sysfs中的目录名称 */ struct list_head entry; /* kobjetct双向链表 */ struct kobject *parent; /* 指向kset中的kobject,相当于指向父目录 */ struct kset *kset; /*指向所属的kset*/ struct kobj_type *ktype; /*负责对kobject结构跟踪*/ .;/* 定义kobject的类型及释放回调 */struct kobj_type void (*release)(struct kobjec
6、t *); /* kobject释放函数指针 */ struct sysfs_ops *sysfs_ops; /* 默认属性操作方法 */ struct attribute *default_attrs; /* 默认属性 */;/* kobject上层容器 */struct kset struct list_head list; /* 用于连接kset中所有kobject的链表头 */ spinlock_t list_lock; /* 扫描kobject组成的链表时使用的锁 */ struct kobject kobj; /* 嵌入的kobject */ const struct kset_u
7、event_ops *uevent_ops; /* kset的uevent操作 */;/* 包含kset的更高级抽象 */struct subsystem struct kset kset; /* 定义一个kset */ struct rw_semaphore rwsem; /* 用于串行访问kset内部链表的读写信号量 */;kobject和kset关系:如图所示,kset将它的children(kobjects)组成一个标准的内核链表。所以说kset是一个包含嵌入在同种类型结构中的kobject的集合。它自身也内嵌一个kobject,所以也是一个特殊的kobject。设计kset的主要目的
8、是容纳,可以说是kobject的顶层容器。kset总是会在sysfs中以目录的形式呈现。需要注意的是图中所示的kobject其实是嵌入在其他类型中(很少单独使用),也可能是其他kset中。kset和subsystem关系:一个子系统subsystem, 其实只是一个附加了个读写信号量的kset的包装,反过来就是说每个 kset 必须属于一个子系统。根据subsystem之间的成员关系建立kset在整个层级中的位置。子系统常常使用宏直接静态定义:/* 定义一个struct subsystem name_subsys 并初始化kset的type及hotplug_ops */ decl_subsys
9、(name, struct kobj_type *type,struct kset_hotplug_ops *hotplug_ops);操作函数初始化/* 初始化kobject内部结构 */void kobject_init(struct kobject *kobj);/* 设置name */int kobject_set_name(struct kobject *kobj, const char *format, .);/* 先将kobj-kset指向要添加的kset中,然后调用会将kobject加入到指定的kset中 */int kobject_add(struct kobject *ko
10、bj);/* kobject_register = kobject_init + kobject_add */extern int kobject_register(struct kobject *kobj);/* 对应的Kobject删除函数 */void kobject_del(struct kobject *kobj);void kobject_unregister(struct kobject *kobj);/* 与kobject类似的kset操作函数 */void kset_init(struct kset *kset);kobject_set_name(int kset_add(s
11、truct kset *kset);int kset_register(struct kset *kset);void kset_unregister(struct kset *kset);TIp: 初始化前应先使用memset将kobj清零;初始化完成后引用计数为1引用计数管理/* 引用计数加1并返回指向kobject的指针 */struct kobject *kobject_get(struct kobject *kobj);/* 当一个引用被释放, 调用kobject_put递减引用计数,当引用为0时free这个object */void kobject_put(struct kobje
12、ct *kobj);/* 与kobject类似的kset操作函数 */struct kset *kset_get(struct kset *kset);void kset_put(struct kset *kset);释放当引用计数为0时,会调用ktype中的release,因此可以这样定义release回调函数:void my_object_release(struct kobject *kobj) struct my_object *mine = container_of(kobj, struct my_object, kobj); /* Perform any additional cl
13、eanup on this object, then. */ kfree(mine);/* 查找ktype */struct kobj_type *get_ktype(struct kobject *kobj);subsystem相关decl_subsys(name, type, hotplug_ops);void subsystem_init(struct subsystem *subsys);int subsystem_register(struct subsystem *subsys);void subsystem_unregister(struct subsystem *subsys)
14、;struct subsystem *subsys_get(struct subsystem *subsys);void subsys_put(struct subsystem *subsys);Low-Level Sysfs Operationskobject和sysfs关系kobject是实现sysfs虚拟文件系统背后的机制。sysfs中的每一个目录都对应内核中的一个kobject。将kobject的属性(atrributes)导出就会在sysfs对应的目录下产生由内核自动生成的包含这些属性信息的文件。只需简单的调用前面所提到的kobject_add就会在sysfs中生成一个对应kobje
15、ct的入口,但值得注意的是:这个入口总会以目录呈现, 也就是说生成一个入口就是创建一个目录。通常这个目录会包含一个或多个属性文件(见下文)。分配给kobject的名字(用kobject_set_name)就是给 sysfs 目录使用的名字,因此在sysfs层级中相同部分的kobject命名必须唯一,不能包含下划线,避免使用空格。这个入口所处的目录表示kobject的parent指针,如果parent为NULL,则指向的是它的kset,因此可以说sysfs的层级其实对应的就是kset的层级。但当kset也为NULL时,这个入口就会创建在sysfs的top level,不过实际中很少出现这种情况。
16、属性(atrributes)属性即为上面所提到的一旦导出就会由内核自动生成的包含kobject内核信息的文件。结构如下:struct attribute char *name; /* 属性名,也是sysfs对应entry下的文件名 */ struct module *owner; /* 指向负责实现这个属性的模块 */ mode_t mode; /* 权限位,在中定义 */;属性的导出显示及导入存储函数:/* kobj: 需要处理的kobject attr: 需要处理的属性 buffer: 存储编码后的属性信息,大小为PAGE_SIZE return: 实际编码的属性信息长度 */struct
17、 sysfs_ops ssize_t (*show)(struct kobject *kobj, struct attribute *attr,char *buffer); /* 导出到用户空间 */ ssize_t (*store)(struct kobject *kobj, struct attribute *attr,const char *buffer, size_t size); /* 存储进内核空间 */;需要注意的是:每个属性都是用name=value表示,name即使属性的文件名,value即文件内容,如果value超过PAGE_SIZE,则应分为多个属性来处理;上述函数可以处
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 了解 Linux 设备 驱动 模型
链接地址:https://www.31doc.com/p-3371930.html