设为首页 加入收藏

TOP

Linux驱动之设备模型(一)
2014-11-24 13:53:45 来源: 作者: 【 】 浏览:7
Tags:Linux 驱动 设备 模型

1.Overview


l 设备模型是2.6内核引入的新特性,提供了一个一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构,使得系统具有以下优点:


n 代码重复最小化


n 提供诸如引用计数这样的统一机制


n 可以列举系统中所有的设备,观察它们的状态,并查看它们连接的总线


n 可以将系统中的全部设备结构以树的形式完整、有效地展现出来


n 可以将设备和其对应的驱动联系起来,反之亦然


n 可以将设备按照类型加以归类,比如归类为输入设备,而无需理解物理设备的拓扑结构


n 可以沿设备树的叶子向其根的方向依次遍历,以保证能以正确顺序关闭个设备的电源


最后一点是实现设备模型的最初动机。



l 作为Linux驱动工程师,掌握设备模型是非常必要的。掌握了设备驱动模型,再去阅读内核源码,发现自己会在一个更高的高度阅读代码。



2. kobject


2.1 overview


设备模型的核心部分就是kobject(kernel object),由struct kobject结构体表示,在sysfs中表现为一个目录。



2.2 kobject结构体


l Kobject是组成设备模型的基本结构,通常嵌入到其它结构体中,这样就可以通过kobject来访问该结构体


struct kobject {


const char *name; /* kobject名称 */


struct list_head entry; /* 用于链入所属的kset的链表 */


struct kobject *parent; /* 指向kobject的父对象 */


struct kset *kset; /* 所属kset */


struct kobj_type *ktype; /* 所属ktype */


struct sysfs_dirent *sd; /* sysfs中的目录项 */


struct kref kref; /* 提供引用计数 */


unsigned intstate_initialized:1; /* 标志:初始化 */


unsigned intstate_in_sysfs:1; /* 标志:在sysfs中 */


unsigned intstate_add_uevent_sent:1; /* 标志:已发出KOBJ_ADDuevent */


unsigned intstate_remove_uevent_sent:1;/* 标志:已发出KOBJ_REMOVE uevent */


unsigned intuevent_suppress:1; /* 标志:禁止发出uevent*/


};



2.3 kobject的基本操作


Kobject操作函数实现在kobject.c文件中,这里介绍常用的几个


l 初始化


voidkobject_init(struct kobject *kobj, struct kobj_type *ktype)


l Kobject添加,在sysfs产生一个目录


intkobject_add(struct kobject *kobj, struct kobject *parent,


constchar *fmt, ...)


l 初始化和添加


intkobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,


struct kobject *parent, const char *fmt, ...)


l 创建和添加


struct kobject *kobject_create_and_add(const char *name,struct kobject *parent)


l 删除


void kobject_del(struct kobject *kobj)


l 引用数加一


struct kobject*kobject_get(struct kobject *kobj)


l 引用数减一,当引用计数减到0时,会调用release函数进行销毁工作


voidkobject_put(struct kobject *kobj)



2.3 实例解析


创建一个kobject,并建立一个属性文件


/*


* forlearn kobject


*/


#include


#include


#include


#include


#include



static int n = 6;


/* 当用户空间读取一个属性时,有调用到此方法把指定的值编码后放入缓冲区 */


static ssize_t sc_show(struct kobject*kobj,


structkobj_attribute *attr, char *buf)


{


returnsprintf(buf, "%d\n", n);


}


/* 当用户空间写入一个属性时,有调用到此方法把指定的值解码后放入传递给相应变量 */


static ssize_t sc_store(struct kobject*kobj,


structkobj_attribute *attr, const char *buf, size_t count)


{


sscanf(buf,"%du", &n);


returncount;


}



/* 构建kobject的属性 */


static struct kobj_attribute sc_attrb =


__ATTR(sc_example,0666, sc_show, sc_store);



static struct kobject *kobj;



static int __init example_init(void)


{


intret;



/*create kobject, a dir(kobj_example) in sys/ */


kobj= kobject_create_and_add("kobj_example", NULL);


if(!kobj)


return- ENOMEM;



/*create a attribute file(sc_example) in kobj_example */


ret= sysfs_create_file(kobj, &sc_attrb.attr);


if(ret)


gotoattr_file_failed;


return0;



attr_file_failed:


kobject_put(kobj);


returnret;


}



static void __exit example_exit(void)


{


sysfs_remove_file(kobj,&sc_attrb.attr);


首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇php 读取,分割大文件详解 下一篇Android开发教程:ListView下拉回..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: