1.Overview
l 设备模型是2.6内核引入的新特性,提供了一个独立的机制专门来表示设备,并描述其在系统中的拓扑结构,使得系统具有以下优点:
n 代码重复最小化
n 提供诸如引用计数这样的统一机制
n 可以列举系统中所有的设备,观察它们的状态,并查看它们连接的总线
n 可以将系统中的全部设备结构以树的形式完整、有效地展现出来
n 可以将设备和其对应的驱动联系起来,反之亦然
n 可以将设备按照类型加以归类,比如归类为输入设备,而无需理解物理设备的拓扑结构
n 可以沿设备树的叶子向其根的方向依次遍历,以保证能以正确顺序关闭个设备的电源
最后一点是实现设备模型的最初动机。
l 作为Linux驱动工程师,掌握设备模型是非常必要的。掌握了设备驱动模型,再去阅读内核源码,发现自己会在一个更高的高度阅读代码。
2. kobject
2.1 overview
设备模型的核心部分就是kobject(kernel object),由structkobject结构体表示,在sysfs中表现为一个目录。
2.2 kobject结构体
l Kobject是组成设备模型的基本结构,通常嵌入到其它结构体中,这样就可以通过kobject来访问该结构体
struct kobject {
constchar *name;
structlist_head entry;
structkobject *parent;
structkset *kset;
structkobj_type *ktype;
struct sysfs_dirent *sd;
structkref kref;
unsigned intstate_initialized:1;
unsignedintstate_in_sysfs:1;
unsignedintstate_add_uevent_sent:1;
unsigned intstate_remove_uevent_sent:1;
unsignedintuevent_suppress:1;
};
2.3 kobject的基本操作
Kobject操作函数实现在kobject.c文件中,这里介绍常用的几个
l 初始化
void kobject_init(structkobject *kobj, struct kobj_type *ktype)
l Kobject添加,在sysfs产生一个目录
int kobject_add(structkobject *kobj, struct kobject *parent,
constchar *fmt, ...)
l 初始化和添加
int kobject_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(structkobject *kobj)
l 引用数加一
struct kobject* kobject_get(structkobject *kobj)
l 引用数减一,当引用计数减到0时,会调用release函数进行销毁工作
void kobject_put(structkobject *kobj)
2.3 实例解析
创建一个kobject,并建立一个属性文件
#include
#include
#include
#include
#include
static int n = 6;
static ssize_t sc_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", n);
}
static ssize_t sc_store(structkobject*kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
sscanf(buf,"%du", &n);
return count;
}
static structkobj_attribute sc_attrib =
__ATTR(sc_example,0666, sc_show, sc_store);
static struct kobject *kobj;
static int __init example_init(void)
{
int ret;
kobj=kobject_create_and_add("kobj_example", NULL);
if(!kobj)
return- ENOMEM;
ret= sysfs_create_file(kobj,&sc_attrb.attr); //两个参数
if(ret)
goto attr_file_failed;
return 0;
attr_file_failed:
kobject_put(kobj);
return ret;
}
static void __exit example_exit(void)
{
sysfs_remove_file(kobj,&sc_attrib.attr);
kobject_put(kobj);
}
module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("CJOK");
试验结果: