你知道Linux设备驱动模型是怎么样构成的?.doc
《你知道Linux设备驱动模型是怎么样构成的?.doc》由会员分享,可在线阅读,更多相关《你知道Linux设备驱动模型是怎么样构成的?.doc(17页珍藏版)》请在三一办公上搜索。
1、你知道Linux设备驱动模型是怎么样构成的?尽管LDD3中说对多数程序员掌握设备驱动模型不是必要的,但对于嵌入式Linux的底层程序员而言,对设备驱动模型的学习非常重要。Linux设备模型的目的:为内核建立一个统一的设备模型,从而又一个对系统结构的一般性抽象描述。换句话说,Linux设备模型提取了设备操作的共同属性,进行抽象,并将这部分共同的属性在内核中实现,而为需要新添加设备或驱动提供一般性的统一接口,这使得驱动程序的开发变得更简单了,而程序员只需要去学习接口就行了。在正式进入设备驱动模型的学习之前,有必要把documentation/filesystems/sysfs.txt读一遍(不能偷
2、懒)。sysfs.txt主要描述/sys目录的创建及其属性,sys目录描述了设备驱动模型的层次关系,我们可以简略看一下/sys目录,block:所有块设备devices:系统所有设备(块设备特殊),对应struct device的层次结构bus:系统中所有总线类型(指总线类型而不是总线设备,总线设备在devices下),bus的每个子目录都包含-devices:包含到devices目录中设备的软链接-drivers:与bus类型匹配的驱动程序class:系统中设备类型(如声卡、网卡、显卡等)fs:一些文件系统,具体可参考filesystems /fuse.txt中例子dev:包含2个子目录-c
3、har:字符设备链接,链接到devices目录,以:命名-block:块设备链接Linux设备模型学习分为:Linux设备底层模型,描述设备的底层层次实现(kobject);Linux上层容器,包括总线类型(bus_type)、设备(device)和驱动(device_driver)。=Linux设备底层模型 =谨记:像上面看到的一样,设备模型是层次的结构,层次的每一个节点都是通过kobject实现的。在文件上则体现在sysfs文件系统。kobject结构内核中存在struct kobject数据结构,每个加载到系统中的kobject都唯一对应/sys或者子目录中的一个文件夹。可以这样说,许多
4、kobject结构就构成设备模型的层次结构。每个kobject对应一个或多个struct attribute描述属性的结构。点击(此处)折叠或打开struct kobjectconstchar*name;/*对应sysfs的目录名*/struct list_head entry;/*kobjetct双向链表*/struct kobject*parent;/*指向kset中的kobject,相当于指向父目录*/struct kset*kset;/*指向所属的kset*/struct kobj_type*ktype;/*负责对kobject结构跟踪*/struct sysfs_dirent*sd;
5、struct kref kref;/*kobject引用计数*/unsignedintstate_iniTIalized:1;unsignedintstate_in_sysfs:1;unsignedintstate_add_uevent_sent:1;unsignedintstate_remove_uevent_sent:1;unsignedintuevent_suppress:1;kobject结构是组成设备模型的基本结构,最初kobject设计只用来跟踪模块引用计数,现已增加支持,sysfs表述:在sysfs中的每个对象都有对应的kobject 数据结构关联:通过链接将不同的层次数据关联
6、热插拔事件处理:kobject子系统将产生的热插拔事件通知用户空间kobject一般不单独使用,而是嵌入到上层结构(比如struct device,struct device_driver)当中使用。kobject的创建者需要直接或间接设置的成员有:ktype、kset和parent。kset我们后面再说,parent设置为NULL时,kobject默认创建到/sys顶层目录下,否则创建到对应的kobject目录中。重点来分析ktype成员的类型,点击(此处)折叠或打开#includestruct kobj_typevoid(*release)(struct kobject*kobj);/*释
7、放*/conststruct sysfs_ops*sysfs_ops;/*默认属性实现*/struct attribute*default_attrs;/*默认属性*/conststruct kobj_ns_type_operaTIons*(*child_ns_type)(struct kobject*kobj);constvoid*(*namespace)(struct kobject*kobj);ktype包含了释放设备、默认属性以及属性的实现方法几个重要成员。每个kobject必须有一个release方法,并且kobject在该方法被调用之前必须保持不变(处于稳定状态)。默认属性的结构如
8、下,点击(此处)折叠或打开#includestruct attributeconstchar*name;/*属性名称*/mode_t mode;/*属性保护:只读设为S_IRUGO,可写设为S_IWUSR*/kobj_type中的default_attrs为二级结构指针,可以对每个kobject使用多个默认属性,最后一个属性使用NULL填充。struct sysfs_ops结构则如下,点击(此处)折叠或打开struct sysfs_opsssize_t(*show)(struct kobject*,struct attribute*,char*);ssize_t(*store)(struct
9、kobject*,struct attribute*,constchar*,size_t);show方法用于将传入的指定属性编码后放到char *类型的buffer中,store则执行相反功能:将buffer中的编码信息解码后传递给struct attribute类型变量。两者都是返回实际的属性长度。一个使用kobject的简单例子如下,点击(此处)折叠或打开#include#include#include#include#include#includeMODULE_AUTHOR(xhzuoxin);MODULE_LICENSE(Dual BSD/GPL);void my_obj_releas
10、e(struct kobject*kobj)printk(release ok.n);ssize_t my_sysfs_show(struct kobject*kobj,struct attribute*attr,char*buf)printk(my_sysfs_show.n);printk(attrname:%s.n,attr-name);sprintf(buf,%s,attr-name);return strlen(attr-name)+1;ssize_t my_sysfs_store(struct kobject*kobj,struct attribute*attr,constchar*
11、buf,size_t count)printk(my_sysfs_store.n);printk(write:%sn,buf);return count;struct sysfs_ops my_sysfs_ops=.show=my_sysfs_show,.store=my_sysfs_store,;struct attribute my_attrs=.name=zx_kobj,.mode=S_IRWXUGO,;struct attribute*my_attrs_def=NULL,;struct kobj_type my_ktype=.release=my_obj_release,.sysfs_
12、ops=.default_attrs=my_attrs_def,;struct kobject my_kobj;int_init kobj_test_init(void)printk(kobj_test init.n);kobject_init_and_add(return 0;void _exit kobj_test_exit(void)printk(kobj_test exit.n);kobject_del(module_init(kobj_test_init);module_exit(kobj_test_exit);例子中有两个函数,用于初始化添加和删除kobject结构,点击(此处)折
13、叠或打开intkobject_init_and_add(struct kobject*kobj,struct kobj_type*ktype,struct kobject*parent,constchar*fmt,.);/*fmt指定kobject名称*/void kobject_del(struct kobject*kobj);加载模块后,在/sys目录下增加了一个叫zx达到目录,zx目录下创建了一个属性文件zx_kobj,使用tree /sys/zx查看。内核提供了许多与kobject结构相关的函数,如下:点击(此处)折叠或打开/kobject初始化函数void kobject_init(
14、struct kobject*kobj);/设置指定kobject的名称intkobject_set_name(struct kobject*kobj,constchar*format,.);/将kobj 对象的引用计数加,同时返回该对象的指针struct kobject*kobject_get(struct kobject*kobj);/将kobj对象的引用计数减,如果引用计数降为,则调用kobject release()释放该kobject对象void kobject_put(struct kobject*kobj);/将kobj对象加入Linux设备层次。挂接该kobject对象到kse
15、t的list链中,增加父目录各级kobject的引/用计数,在其parent指向的目录下创建文件节点,并启动该类型内核对象的hotplug函数intkobject_add(struct kobject*kobj);/kobject注册函数,调用kobject init()初始化kobj,再调用kobject_add()完成该内核对象的注册intkobject_register(struct kobject*kobj);/从Linux设备层次(hierarchy)中删除kobj对象void kobject_del(struct kobject*kobj);/kobject注销函数.与kobjec
16、t register()相反,它首先调用kobject del从设备层次中删除该对象,再调/用kobject put()减少该对象的引用计数,如果引用计数降为,则释放kobject对象void kobject_unregister(struct kobject*kobj);kset结构我们先看上图,kobject通过kset组织成层次化的结构,kset将一系列相同类型的kobject使用(双向)链表连接起来,可以这样 认为,kset充当链表头作用,kset内部内嵌了一个kobject结构。内核中用kset数据结构表示为:点击(此处)折叠或打开#includestruct ksetstruct
17、list_head list;/*用于连接kset中所有kobject的链表头*/spinlock_t list_lock;/*扫描kobject组成的链表时使用的锁*/struct kobject kobj;/*嵌入的kobject*/conststruct kset_uevent_ops*uevent_ops;/*kset的uevent操作*/;与kobject相似,kset_init()完成指定kset的初始化,kset_get()和kset_put()分别增加和减少kset对象的引用计数。Kset_add()和kset_del()函数分别实现将指定keset对象加入设备层次和从其中删除
18、;kset_register()函数完成kset的注册而kset_unregister()函数则完成kset的注销。= 设备模型上层容器 =这里要描述的上层容器包括总线类型(bus_type)、设备(device)和驱动(device_driver),这3个模型环环相扣,参考图9-2。为何称为容器?因为bus_type/device/device_driver结构都内嵌了Linux设备的底层模型(kobject结构)。为什么称为上层而不是顶层?因为实际的驱动设备结构往往内嵌bus_type/device/device_driver这些结构,比如pci,usb等。总线类型、设备、驱动3者之间关系
19、:在继续之前,自我感觉需要区分2个概念:总线设备与总线类型。总线设备本质上是一种设备,也需要像设备一样进行初始化,但位于设备的最顶层,总线类型是一种在设备和驱动数据结构中都包含的的抽象的描述(如图9-2),总线类型在/sys/bus目录下对应实体,总线设备在/devices目录下对应实体。总线类型bus_type内核对总线类型的描述如下:点击(此处)折叠或打开struct bus_typeconstchar*name;/*总线类型名*/struct bus_attribute*bus_attrs;/*总线的属性*/struct device_attribute*dev_attrs;/*设备属性
20、,为每个加入总线的设备建立属性链表*/struct driver_attribute*drv_attrs;/*驱动属性,为每个加入总线的驱动建立属性链表*/*驱动与设备匹配函数:当一个新设备或者驱动被添加到这个总线时,这个方法会被调用一次或多次,若指定的驱动程序能够处理指定的设备,则返回非零值。必须在总线层使用这个函数,因为那里存在正确的逻辑,核心内核不知道如何为每个总线类型匹配设备和驱动程序*/int(*match)(struct device*dev,struct device_driver*drv);/*在为用户空间产生热插拔事件之前,这个方法允许总线添加环境变量(参数和 kset 的u
21、event方法相同)*/int(*uevent)(struct device*dev,struct kobj_uevent_env*env);int(*probe)(struct device*dev);/*/int(*remove)(struct device*dev);/*设备移除调用操作*/void(*shutdown)(struct device*dev);int(*suspend)(struct device*dev,pm_message_t state);int(*resume)(struct device*dev);conststruct dev_pm_ops*pm;struct
22、 subsys_private*p;/*一个很重要的域,包含了device链表和drivers链表*/;接着对bus_type中比较关注的几个成员进行简述,1 struct bus_attribute结构,device_attribute与driver_attribute将分别在设备和驱动分析过程中看到,点击(此处)折叠或打开struct bus_attributestruct attribute attr;ssize_t(*show)(struct bus_type*bus,char*buf);ssize_t(*store)(struct bus_type*bus,constchar*buf
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 知道 Linux 设备 驱动 模型 怎么样 构成
链接地址:https://www.31ppt.com/p-4923383.html