Linux设备驱动编程模型之上层容器篇Word下载.docx

上传人:b****5 文档编号:20863424 上传时间:2023-01-26 格式:DOCX 页数:39 大小:96.40KB
下载 相关 举报
Linux设备驱动编程模型之上层容器篇Word下载.docx_第1页
第1页 / 共39页
Linux设备驱动编程模型之上层容器篇Word下载.docx_第2页
第2页 / 共39页
Linux设备驱动编程模型之上层容器篇Word下载.docx_第3页
第3页 / 共39页
Linux设备驱动编程模型之上层容器篇Word下载.docx_第4页
第4页 / 共39页
Linux设备驱动编程模型之上层容器篇Word下载.docx_第5页
第5页 / 共39页
点击查看更多>>
下载资源
资源描述

Linux设备驱动编程模型之上层容器篇Word下载.docx

《Linux设备驱动编程模型之上层容器篇Word下载.docx》由会员分享,可在线阅读,更多相关《Linux设备驱动编程模型之上层容器篇Word下载.docx(39页珍藏版)》请在冰豆网上搜索。

Linux设备驱动编程模型之上层容器篇Word下载.docx

图一是挂载于/sys目录下的sysfs文件系统的局部视图。

/sys

|—block/

|–fd0

|–hda

|–dev

|–device->

../../devices/pci0000:

00/0000:

00:

1f.1/ide0/0.0

|–bus/

|–class/

|–devices/

|–firmware/

|–power/

|–module/

Sysfs的根目录下包含了七个目录:

block, 

bus, 

class,devices, 

firmware, 

module和power。

block目录下的每个子目录都对应着系统中的一个块设备。

反过来,每个目录下又都包含了该块设备的所有分区。

bus目录提供了一个系统总线视图。

class目录包含了以高层功能逻辑组织起来的系统设备视图。

devices目录是系统中设备拓扑结构视图,它直接映射出了内核中设备结构体的组织层次。

firmware目录包含了一些诸如ACPI,EDD,EFI等低层子系统的特殊树。

power目录包含了系统范围的电源管理数据。

其中最重要的目录是devices,该目录将设备模型导出到用户空间。

目录结构就是系统中实际的设备拓扑。

其它目录中的很多数据都是将devices目录下的数据加以转换加工而得。

比如,/sys/class/net/目录是以注册网络接口这一高层概念来组织设备关系的,在这个目中可能会有目录eth0,它里面包含的devices文件其实就是一个指回到devices下实际设备目录的符号连接。

随便看看任何你可访问到的Linux系统,这种系统设备视图相当准确和漂亮,而且可以看到class中的高层概念与devices中的低层物理设备,以及bus中的实际驱动程序之间互相联络是非常广泛的。

Sysfs文件系统的目标就是要展现设备驱动模型组件之间的层次关系。

在Linux中,sysfs文件系统被安装于/sys目录下:

mount 

-t 

sysfs 

那么,在这样的目录树中,哪些目录是驱动模型要关注的对象?

bus-系统中用于连接设备的总线,在内核中对应的结构体为 

struct 

bus_type 

… 

};

device-内核所识别的所有设备,依照连接它们的总线对其进行组织, 

对应的结构体为struct 

device 

class-系统中设备的类型(声卡,网卡,显卡,输入设备等),同一类中包含的设备可能连接到不同的总线, 

对应的结构体为 

class 

为什么不对Power进行单独描述?

实际上,Power与device有关,它只是device中的一个字段。

除此之外,立马闪现在我们脑子里的对象还有:

driver-在内核中注册的设备驱动程序, 

对应的结构体为

device_driver{ 

以上bus,device,class,driver,是可以感受到的对象,在内核中都用相应的结构体来描述。

而实际上,按照面向对象的思想,我们需要抽象出一个最基本的对象,这就是设备模型的核心对象kobject.

Kobject 

是Linux 

2.6引入的新的设备管理机制,在内核中就是一个struct 

kobject结构体。

有了这个数据结构,内核中所有设备在底层都具有统一的接口,kobject提供基本的对象管理,是构成Linux2.6设备模型的核心结构,它与sysfs文件系统紧密关联,每个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录。

Kobject是组成设备模型的基本结构。

类似于C++中的基类,它嵌入于更大的对象中,即所谓的容器,如上面提到的bus,class,devices, 

drivers 

都是典型的容器,它们是描述设备模型的组件。

二、主要对象介绍

1,核心对象kobject

话说kobject是驱动模型的核心对象,但在sysfs文件系统中似乎并没有对应的项,而这种看似“无”,实际上蕴藏着“有”。

这“有”从何说起。

回想文件系统中的核心对象“索引节点(indoe)”和目录项“dentry”:

Inode—与文件系统中的一个文件相对应(而实际上,只有文件被访问时,才在内存创建索引节点)。

Dentry-每个路径中的一个分量,例如路径/bin/ls,其中/、 

bin 

和ls三个都是目录项,只是前两个是目录,而最后一个是普通文件。

也就是说,目录项目录项或者是一子目录,或者是一个文件。

从上面的定义可以看出,indoe和dentry谁的包容性更大?

当然是dentry!

那么,kobject与dentry有何关系?

由此我们可以推想,把dentry作为kobject中的一个字段,恍然间,kobject变得强大起来了。

何谓“强大“,因为这样以来,就可以方便地将kobject映射到一个dentry上,也就是说,kobject与/sys下的任何一个目录或文件相对应了,进一步说,把kobject导出形成文件系统就变得如同在内存中构建目录项一样简单。

由此可知,kobject其实已经形成一棵树了。

这就是以隐藏在背后的对象模型为桥梁,将驱动模型和sysfs文件系统全然联系起来。

由于kobject被映射到目录项,同时对象模型层次结构也已经在内存形成一个树,因此sysfs的形成就水到渠成了。

既然,kobject要形成一颗树,那么其中的字段就要有parent,以表示树的层次关系;

另外,kobject不能是无名氏,得有name字段,按说,目录或文件名并不会很长,但是,sysfs文件系统为了表示对象之间复杂的关系,需要通过软链接达到,而软链接常常有较长的名字。

[cpp]viewplaincopyprint?

1./*设备驱动程序模型的核心数据结构,每个kobject 

2.数据结构对应于sysfs文件系统中的一个目录*/ 

3.struct 

kobject 

4. 

const 

char 

*name;

/*指向含有容器名称的字符*/ 

5. 

list_head 

entry;

/*用于kobject所插入的链表的指针*/ 

6. 

*parent;

/*指向父kobject*/ 

7. 

kset 

*kset;

/*指向包含的kset*/ 

8. 

kobj_type 

*ktype;

/*指向kobject的类型的描述符*/ 

9. 

sysfs_dirent 

*sd;

/*用同一种 

来统一设备模型中的 

kset/kobject/attr/attr_group.*/ 

10. 

kref 

kref;

/*容器的引用计数器*/ 

11. 

unsigned 

int 

state_initialized:

1;

/*指明kobject是否被初始化*/ 

12. 

state_in_sysfs:

/*指明是否使用了sysfs*/ 

13. 

state_add_uevent_sent:

/*热插拔加载事件*/ 

14. 

state_remove_uevent_sent:

/*热插拔卸载事件*/ 

15. 

uevent_suppress:

/*如果设置了uevent_suppress字段,说明不希望产生事件,忽略事件正确返回*/ 

16.};

/*设备驱动程序模型的核心数据结构,每个kobject

数据结构对应于sysfs文件系统中的一个目录*/

structkobject{

constchar*name;

/*指向含有容器名称的字符*/

structlist_headentry;

/*用于kobject所插入的链表的指针*/

structkobject*parent;

/*指向父kobject*/

structkset*kset;

/*指向包含的kset*/

structkobj_type*ktype;

/*指向kobject的类型的描述符*/

structsysfs_dirent*sd;

/*用同一种structsysfs_dirent来统一设备模型中的kset/kobject/attr/attr_group.*/

structkrefkref;

/*容器的引用计数器*/

unsignedintstate_initialized:

/*指明kobject是否被初始化*/

unsignedintstate_in_sysfs:

/*指明是否使用了sysfs*/

unsignedintstate_add_uevent_sent:

/*热插拔加载事件*/

unsignedintstate_remove_uevent_sent:

/*热插拔卸载事件*/

unsignedintuevent_suppress:

/*如果设置了uevent_suppress字段,说明不希望产生事件,忽略事件正确返回*/

2. 

引用计数kref 

kobject的主要功能之一就是为我们提供了一个统一的引用计数系统,为什么说它具有“统一”的能力?

那是因为kobject是“基”对象,就像大厦的基地,其他对象(如devic,bus,class,device_driver等容器)都将其包含,以后,其他对象的引用技术继承或封装kobject的引用技术就可以了。

初始化时,kobject的引用计数设置为1。

只要引用计数不为零,那么该对象就会继续保留在内存中,也可以说是被“钉住”了。

任何包含对象引用的代码首先要增加该对象的引用计数,当代码结束后则减少它的引用计数。

增加引用计数称为获得(getting)对象的引用,减少引用计数称为释放(putting)对象的引用。

当引用计数跌到零时,对象便可以被销毁,同时相关内存也都被释放。

增加一个引用计数可通过koject_get()函数完成:

kobject_get(struct 

*kobj);

该函数正常情况下将返回一个指向kobject的指针,如果失败则返回NULL指针;

减少引用计数通过kobject_put()完成:

void 

kobject_put(struct 

如果对应的kobject的引用计数减少到零,则与该kobject关联的ktype中的析构函数将被调用。

我们深入到引用计数系统的内部去看,会发现kobject的引用计数是通过kref结构体实现的,该结构体定义在头文件<

linux/kref.h>

中:

atomic_t 

refcount;

其中唯一的字段是用来存放引用计数的原子变量。

那为什么采用结构体?

这是为了便于进行类型检测。

在使用kref前,必须先通过kref_init()函数来初始化它:

voidkref_init(structkref*kref){atomic_set(&

kref->

refcount,1);

}

正如你所看到的,这个函数简单的将原子变量置1,所以kref一但被初始化,它表示的引用计数便固定为1。

开发者现在不必在内核代码中利用atmoic_t类型来实现其自己的引用计数。

对开发者而言,在内核代码中最好的方法是利用kref类型和它相应的辅助函数,为自己提供一个通用的、正确的引用计数机制。

上述的所有函数定义与声明分别在在文件lib/kref.c和文件<

中。

3. 

共同特性的ktype

如上所述,kobject是一个抽象而基本的对象。

对于一族具有共同特性的kobject,就是用ktype来描述:

1.struct 

2. 

(*release)(struct 

3. 

sysfs_ops 

*sysfs_ops;

attribute 

**default_attrs;

5.};

structkobj_type{

void(*release)(structkobject*kobj);

structsysfs_ops*sysfs_ops;

structattribute**default_attrs;

定义于头文件<

linux/kobject.h>

release指针指向在kobject引用计数减至零时要被调用的析构函数。

该函数负责释放所有kobject使用的内存和其它相关清理工作。

sysfs_ops变量指向sysfs_ops结构体,其中包含两个函数,也就是对属性进行操作的读写函数show()和store()。

最后,default_attrs指向一个attribute结构体数组。

这些结构体定义了kobject相关的默认属性。

属性描述了给定对象的特征,其实,属性就是对应/sys树形结构中的叶子结点,也就是文件。

4. 

对象集合体kset 

Kset,顾名思义就是kobject对象的集合体,可以把它看成是一个容器,可将所有相关的kobject对象聚集起来,比如“全部的块设备”就是一个kset。

听起来kset与ktypes非常类似,好像没有多少实质内容。

那么“为什么会需要这两个类似的东西呢”。

ksets可把kobject集中到一个集合中,而ktype描述相关类型kobject所共有的特性,它们之间的重要区别在于:

具有相同ktype的kobject可以被分组到不同的ksets。

kobject的kset指针指向相应的kset集合。

kset集合由kset结构体表示,定义于头文件<

list;

/*包含在kset中的kobject类型的描述符*/ 

spinlock_t 

list_lock;

/*嵌入的kobject结构,位于kset中的kobject,其parent字段指向这个内嵌的 

kobject指针*/ 

kobj;

/*指向用于处理kobject结构的过滤和热插拔操作的回调函数表*/ 

kset_uevent_ops 

*uevent_ops;

9.};

structkset{

structlist_headlist;

/*包含在kset中的kobject类型的描述符*/

spinlock_tlist_lock;

/*嵌入的kobject结构,位于kset中的kobject,其parent字段指向这个内嵌的

kobject指针*/

structkobjectkobj;

/*指向用于处理kobject结构的过滤和热插拔操作的回调函数表*/

structkset_uevent_ops*uevent_ops;

其中ktype指针指向集合(kset)中kobject对象的类型(ktype),list连接该集合(kset)中所有的kobject对象。

kobj指向的koject对象代表了该集合的基类,uevent_ops指向一个用于处理集合中kobject对象的热插拔操作的结构体。

5,sys文件系统目录实体sysfs_dirent

sysfs文件系统有自己的dirent结构,dirent 

directory 

entry 

(目录实体)。

sysfs中,每一个dentry对应了一个dirent结构,dentry->

_fsdata是一个void的指针,它指向sysfs_dirent结构。

每个kobject结构对应一个dirent结构。

每个文件(包括目录文件)都对应一个sysfs_dirent对象 

在建立目录和文件后,内存中会形成一棵以sysfs_root为根的目录树结构。

属性attribute结构对应sysfs中的文件,也用sysfs_dirent结构表示。

这样sysfs_dirent的组织就是sysfs的树形结构的映射。

1./*struct 

sysfs_dirent就是用来做kobject与dentry的互相转换用的*/ 

2.struct 

s_count;

s_active;

sysfs_di

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1