ImageVerifierCode 换一换
格式:DOCX , 页数:32 ,大小:35.41KB ,
资源ID:5052755      下载积分:12 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/5052755.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(linux设备模型深探.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

linux设备模型深探.docx

1、linux设备模型深探linux设备模型深探时间:2010-09-23 13:25:02来源:网络 作者:未知 点击:452次一:前言Linux设备模型是一个极其复杂的结构体系,在编写驱动程序的时候,通常不会用到这方面的东西,但是。理解这部份内容,对于我们理解linux设备驱动的结构是大有裨益的。我们不但可以在编写程序程序的时候知其然,亦知其所以一:前言Linux设备模型是一个极其复杂的结构体系,在编写驱动程序的时候,通常不会用到这方面的东西,但是。理解这部份内容,对于我们理解linux设备驱动的结构是大有裨益的。我们不但可以在编写程序程序的时候知其然,亦知其所以然。又可以学习到一种极其精致的

2、架构设计方法。由于之前已经详细分析了sysfs文件系统。所以本节的讨论主要集中在设备模型的底层实现上。上层的接口,如pci.,usb ,网络设备都可以看成是底层的封装。二:kobject ,kset和ktypeKobject,kset,kypte这三个结构是设备模型中的下层架构。模型中的每一个元素都对应一个kobject.kset和ktype可以看成是kobject在层次结构与属性结构方面的扩充。将三者之间的关系用图的方示描述如下: 如上图所示:我们知道。在sysfs中每一个目录都对应一个kobject.这些kobject都有自己的parent。在没有指定parent的情况下,都会指向它所属的

3、kset-object。其次,kset也内嵌了kobject.这个kobject又可以指它上一级的parent。就这样。构成了一个空间上面的层次关系。其实,每个对象都有属性。例如,电源管理,执插拨事性管理等等。因为大部份的同类设备都有相同的属性,因此将这个属性隔离开来,存放在ktype中。这样就可以灵活的管理了.记得在分析sysfs的时候。对于sysfs中的普通文件读写操作都是由kobject-ktype-sysfs_ops来完成的.经过上面的分析,我们大概了解了kobject.kset与ktype的大概架设与相互之间的关系。下面我们从linux源代码中的分析来详细研究他们的操作。 三:kob

4、ject,kset和ktype的操作为了说明kobject的操作,先写一个测试模块,代码如下:#include #include #include #include #include #include #include MODULE_AUTHOR(eric xiao);MODULE_LICENSE(Dual BSD/GPL); void obj_test_release(struct kobject *kobject);ssize_t eric_test_show(struct kobject *kobject, struct attribute *attr,char *buf);ssize_

5、t eric_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count); struct attribute test_attr = .name = eric_xiao, .mode = S_IRWXUGO,; static struct attribute *def_attrs = &test_attr, NULL,; struct sysfs_ops obj_test_sysops = .show = eric_test_show, .store = eric_test_s

6、tore,; struct kobj_type ktype = .release = obj_test_release, .sysfs_ops=&obj_test_sysops, .default_attrs=def_attrs,; void obj_test_release(struct kobject *kobject) printk(eric_test: release . ); ssize_t eric_test_show(struct kobject *kobject, struct attribute *attr,char *buf) printk(have show. ); pr

7、intk(attrname:%s. , attr-name); sprintf(buf,%s ,attr-name); return strlen(attr-name)+2; ssize_t eric_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count) printk(havestore ); printk(write: %s ,buf); return count; struct kobject kobj;static int kobject_test_init() p

8、rintk(kboject test init. ); kobject_init_and_add(&kobj,&ktype,NULL,eric_test); return 0; static int kobject_test_exit() printk(kobject test exit. ); kobject_del(&kobj); return 0; module_init(kobject_test_init);module_exit(kobject_test_exit); 加载模块之后,会发现,在/sys下多了一个eric_test目录。该目录下有一个叫eric_xiao的文件。如下所示

9、:rootlocalhost eric_test# lseric_xiao用cat察看此文件:rootlocalhost eric_test# cat eric_xiao eric_xiao再用echo往里面写点东西;rootlocalhost eric_test# echo hello eric_xiaoDmesg的输出如下: have show.attrname:eric_xiao.havestorewrite: hello 如上所示。我们看到了kobject的大概建立过程.我们来看一下kobject_init_and_add()的实现。在这个函数里,包含了对kobject的大部份操作。i

10、nt kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, struct kobject *parent, const char *fmt, .) va_list args; int retval; /初始化kobject kobject_init(kobj, ktype); va_start(args, fmt); /为kobjcet设置名称,在sysfs中建立相关信息 retval = kobject_add_varg(kobj, parent, fmt, args); va_end(args); retur

11、n retval;上面的流程主要分为两部份。一部份是kobject的初始化。在这一部份,它将kobject与给定的ktype关联起来。初始化kobject中的各项结构。另一部份是kobject的名称设置。空间层次关系的设置,具体表现在sysfs文件系统中.对于第一部份,代码比较简单,这里不再赘述。跟踪第二部份,也就是kobject_add_varg()的实现. static int kobject_add_varg(struct kobject *kobj, struct kobject *parent, const char *fmt, va_list vargs) va_list aq;

12、int retval; va_copy(aq, vargs); /设置kobject的名字。即kobject的name成员 retval = kobject_set_name_vargs(kobj, fmt, aq); va_end(aq); if (retval) printk(KERN_ERR kobject: can not set name properly! ); return retval; /设置kobject的parent。在上面的例子中,我们没有给它指定父结点 kobj-parent = parent; /在sysfs中添加kobjcet信息 return kobject_a

13、dd_internal(kobj);设置好kobject-name后,转入kobject_add_internal()。在sysfs中创建空间结构.代码如下:static int kobject_add_internal(struct kobject *kobj) int error = 0; struct kobject *parent; if (!kobj) return -ENOENT; /如果kobject的名字为空.退出 if (!kobj-name | !kobj-name0) pr_debug(kobject: (%p): attempted to be registered w

14、ith empty name! , kobj); WARN_ON(1); return -EINVAL; /取kobject的父结点 parent = kobject_get(kobj-parent); /如果kobject的父结点没有指定,就将kset-kobject做为它的父结点 /* join kset if set, use it as parent if we do not already have one */ if (kobj-kset) if (!parent) parent = kobject_get(&kobj-kset-kobj); kobj_kset_join(kobj

15、); kobj-parent = parent; /调试用 pr_debug(kobject: %s (%p): %s: parent: %s, set: %s , kobject_name(kobj), kobj, _FUNCTION_, parent ? kobject_name(parent) : , kobj-kset ? kobject_name(&kobj-kset-kobj) : ); /在sysfs中创建kobject的相关元素 error = create_dir(kobj); if (error) /v如果创建失败。减少相关的引用计数 kobj_kset_leave(kob

16、j); kobject_put(parent); kobj-parent = NULL; /* be noisy on error issues */ if (error = -EEXIST) printk(KERN_ERR %s failed for %s with -EEXIST, dont try to register things with the same name in the same directory. , _FUNCTION_, kobject_name(kobj); else printk(KERN_ERR %s failed for %s (%d) , _FUNCTI

17、ON_, kobject_name(kobj), error); dump_stack(); else /如果创建成功。将state_in_sysfs建为1。表示该object已经在sysfs中了 kobj-state_in_sysfs = 1; return error;这段代码比较简单,它主要完成kobject父结点的判断和选定,然后再调用create_dir()在sysfs创建相关信息。该函数代码如下:static int create_dir(struct kobject *kobj) int error = 0; if (kobject_name(kobj) /为kobject创建目

18、录 error = sysfs_create_dir(kobj); if (!error) /为kobject-ktype中的属性创建文件 error = populate_dir(kobj); if (error) sysfs_remove_dir(kobj); return error;我们在上面的示例中看到的/sys下的eric_test目录,以及该目录下面的eric_xiao的这个文件就是这里被创建的。我们先看一下kobject所表示的目录创建过程。这是在sysfs_create_dir()中完成的。代码如下:int sysfs_create_dir(struct kobject *

19、kobj) struct sysfs_dirent *parent_sd, *sd; int error = 0; BUG_ON(!kobj); /*如果kobject的parnet存在。就在目录点的目录下创建这个目录。如果没有父结点不存在,就在/sys下面创建结点。在上面的流程中,我们可能并没有为其指定父结点,也没有为其指定kset。*/ if (kobj-parent) parent_sd = kobj-parent-sd; else parent_sd = &sysfs_root; /在sysfs中创建目录 error = create_dir(kobj, parent_sd, kobj

20、ect_name(kobj), &sd); if (!error) kobj-sd = sd; return error;在这里,我们就要联系之前分析过的sysfs文件系统的研究了。如果不太清楚的,可以在找到那篇文章仔细的研读一下。create_dir()就是在sysfs中创建目录的接口,在之前已经详细分析过了。这里不再讲述。接着看为kobject-ktype中的属性创建文件。这是在populate_dir()中完成的。代码如下:static int populate_dir(struct kobject *kobj) struct kobj_type *t = get_ktype(kobj)

21、; struct attribute *attr; int error = 0; int i; if (t & t-default_attrs) for (i = 0; (attr = t-default_attrsi) != NULL; i+) error = sysfs_create_file(kobj, attr); if (error) break; return error;这段代码比较简单。它遍历ktype中的属性。然后为其建立文件。请注意:文件的操作最后都会回溯到ktype-sysfs_ops的show和store这两个函数中. Kobject的创建已经分析完了,接着分析怎么将一

22、个kobject注销掉。注意过程是在kobject_del()中完成的。代码如下:void kobject_del(struct kobject *kobj) if (!kobj) return; sysfs_remove_dir(kobj); kobj-state_in_sysfs = 0; kobj_kset_leave(kobj); kobject_put(kobj-parent); kobj-parent = NULL;该函数会将在sysfs中的kobject对应的目录删除。请注意,属性文件是建立在这个目录下面的。只需要将这个目录删除。属性文件也随之删除。是后,减少相关的引用计数,如果

23、kobject的引用计数为零。则将其所占空间释放. Kset的操作与kobject类似,因为kset中内嵌了一个kobject结构,所以,大部份操作都是集中在kset-kobject上.具体分析一下kset_create_and_add()这个接口,类似上面分析的kobject接口,这个接口也包括了kset的大部分操作.代码如下:struct kset *kset_create_and_add(const char *name, struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj) struct kset *kset;

24、 int error; /创建一个kset kset = kset_create(name, uevent_ops, parent_kobj); if (!kset) return NULL; /注册kset error = kset_register(kset); if (error) /如果注册失败,释放kset kfree(kset); return NULL; return kset;Kset_create()用来创建一个struct kset结构.代码如下:static struct kset *kset_create(const char *name, struct kset_ue

25、vent_ops *uevent_ops, struct kobject *parent_kobj) struct kset *kset; kset = kzalloc(sizeof(*kset), GFP_KERNEL); if (!kset) return NULL; kobject_set_name(&kset-kobj, name); kset-uevent_ops = uevent_ops; kset-kobj.parent = parent_kobj; kset-kobj.ktype = &kset_ktype; kset-kobj.kset = NULL; return kset

26、;我们注意,在这里创建kset时.为其内嵌的kobject指定其ktype结构为kset_ktype.这个结构的定义如下:static struct kobj_type kset_ktype = .sysfs_ops = &kobj_sysfs_ops, .release = kset_release,;属性文件的读写操作全部都包含在sysfs_ops成员里.kobj_sysfs_ops的定义如下:struct sysfs_ops kobj_sysfs_ops = .show = kobj_attr_show, .store = kobj_attr_store,;Show,store成员对应的

27、函数代码如下所示:static ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) struct kobj_attribute *kattr; ssize_t ret = -EIO; kattr = container_of(attr, struct kobj_attribute, attr); if (kattr-show) ret = kattr-show(kobj, kattr, buf); return ret; static ssize_t kobj_attr_store(st

28、ruct kobject *kobj, struct attribute *attr, const char *buf, size_t count) struct kobj_attribute *kattr; ssize_t ret = -EIO; kattr = container_of(attr, struct kobj_attribute, attr); if (kattr-store) ret = kattr-store(kobj, kattr, buf, count); return ret;从上面的代码看以看出.会将struct attribute结构转换为struct kobj_

29、attribte结构.也就是说struct kobj_attribte内嵌了一个struct attribute.实际上,这是和宏_ATTR配合在一起使用的.经常用于group中.在这里并不打算研究group.原理都是一样的.这里列出来只是做个说明而已.创建好了kset之后,会调用kset_register().这个函数就是kset操作的核心代码了.如下:int kset_register(struct kset *k) int err; if (!k) return -EINVAL; kset_init(k); err = kobject_add_internal(&k-kobj); if (err) return err; kobject_uevent(&k-kobj, KOBJ_ADD); return 0;在kset_init()里会初始化kset中的其它字段.然后调用kobject_add_internal()为其内嵌的kobject结构建立空间层次结构.之后因为添加了kset.会产生一个事件.这个事件是通过用户空间的hotplug程序处理的.这就是kset明显不同于ko

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

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