当前位置:文档之家› linux设备模型

linux设备模型

一:前言Linux设备模型是一个极其复杂的结构体系,在编写驱动程序的时候,通常不会用到这方面的东西,但是。

理解这部份内容,对于我们理解linux设备驱动的结构是大有裨益的。

我们不但可以在编写程序程序的时候知其然,亦知其所以然。

又可以学习到一种极其精致的架构设计方法。

由于之前已经详细分析了sysfs文件系统。

所以本节的讨论主要集中在设备模型的底层实现上。

上层的接口,如pci.,usb ,网络设备都可以看成是底层的封装。

二:kobject ,kset和ktypeKobject,kset,kypte这三个结构是设备模型中的下层架构。

模型中的每一个元素都对应一个kobject.kset和ktype可以看成是kobject在层次结构与属性结构方面的扩充。

将三者之间的关系用图的方示描述如下:如上图所示:我们知道。

在sysfs中每一个目录都对应一个kobject.这些kobject都有自己的parent。

在没有指定parent的情况下,都会指向它所属的kset->object。

其次,kset也内嵌了kobject.这个kobject又可以指它上一级的parent。

就这样。

构成了一个空间上面的层次关系。

其实,每个对象都有属性。

例如,电源管理,执插拨事性管理等等。

因为大部份的同类设备都有相同的属性,因此将这个属性隔离开来,存放在ktype中。

这样就可以灵活的管理了.记得在分析sysfs 的时候。

对于sysfs中的普通文件读写操作都是由kobject->ktype->sysfs_ops来完成的.经过上面的分析,我们大概了解了kobject.kset与ktype的大概架设与相互之间的关系。

下面我们从linux源代码中的分析来详细研究他们的操作。

三:kobject,kset和ktype的操作为了说明kobject的操作,先写一个测试模块,代码如下:#include <linux/device.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/string.h>#include <linux/sysfs.h>#include <linux/stat.h>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_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_store,};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 .\n");}ssize_t eric_test_show(struct kobject *kobject, struct attribute *attr,char *buf){printk("have show.\n");printk("attrname:%s.\n", attr->name);sprintf(buf,"%s\n",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\n");printk("write: %s\n",buf);return count;}struct kobject kobj;static int kobject_test_init(){printk("kboject test init.\n");kobject_init_and_add(&kobj,&ktype,NULL,"eric_test");return 0;}static int kobject_test_exit(){printk("kobject test exit.\n");kobject_del(&kobj);return 0;}module_init(kobject_test_init);module_exit(kobject_test_exit);加载模块之后,会发现,在/sys下多了一个eric_test目录。

该目录下有一个叫eric_xiao的文件。

如下所示:[root@localhost eric_test]# lseric_xiao用cat察看此文件:[root@localhost eric_test]# cat eric_xiaoeric_xiao再用echo往里面写点东西;[root@localhost eric_test]# echo hello > eric_xiaoDmesg的输出如下:have show.attrname:eric_xiao.havestorewrite: hello如上所示。

我们看到了kobject的大概建立过程.我们来看一下kobject_init_and_add()的实现。

在这个函数里,包含了对kobject的大部份操作。

int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,struct kobject *parent, const char *fmt, ...){va_list args;int retval;//初始化kobjectkobject_init(kobj, ktype);va_start(args, fmt);//为kobjcet设置名称,在sysfs中建立相关信息retval = kobject_add_varg(kobj, parent, fmt, args);va_end(args);return 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;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!\n");return retval;}//设置kobject的parent。

在上面的例子中,我们没有给它指定父结点kobj->parent = parent;//在sysfs中添加kobjcet信息return kobject_add_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->name[0]) {pr_debug("kobject: (%p): attempted to be registered with empty ""name!\n", kobj);WARN_ON(1);return -EINV AL;}//取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);kobj->parent = parent;}//调试用pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",kobject_name(kobj), kobj, __FUNCTION__,parent ? kobject_name(parent) : "<NULL>",kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");//在sysfs中创建kobject的相关元素error = create_dir(kobj);if (error) {//v如果创建失败。

相关主题