Linux设备驱动---Kobject
尽管采用C语言实现,但Linux设计实现中很多地方都体现着面向对象的思想。Kobject可以看做是Linux设备对象的基类,单独的Kobject没有太多的意义,它只有嵌入到对象结构体中才流光四射。它的一般用法如下:
struct my_obj
{
struct kobject;
……./* 其他自定义结构体成员*/
};
Kobject的一个重要作用是对象生命周期管理。只有在对象引用计数为0后,对象才能被删除。尽管很多情况下我们我们不会直接操作Kobject(Linux已经替我们做了☺),清楚那些调用将导致引用计数变化对理解驱动还是很有帮助的,所谓知其然,知其所以然。总结如下:
增加引用计数:
kobject_init
kobject_get
减少引用计数:
kobject_put
另外Kobject以链表的形式由Kset进行管理
kobject_add 将Kobject添加到链表中
kobject_del 将Kobject从链表中删除
一个简单的驱动例子:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
MODULE_LICENSE(“Dual BSD/GPL”);
struct my_kobject
{
int val;
struct kobject kobj; //注意这里要用变量而不是指针,以便采用
//container_of根据kobj的指针找到my_kobject
//的地址
};
/*======================================================*/
void my_ktype_release(struct kobject *kobj)
{
printk(“===my_ktype_release===\n”);
}
ssize_t my_ktype_show(struct kobject * kobj,
struct attribute *attr, char *buf)
{
ssize_t count = 0;
printk(“===my_ktype_show===\n”);
if(0==strcmp(attr->name,”name”))
{
printk(“%s\n”,kobj->name);
count = sprintf(buf,”%s==>file\n”,kobj->name);
}
else
{
printk(“should not go here\n”);
}
return count;
}
ssize_t my_ktype_store(struct kobeject *kobj,
struct attribute *attr, const char *buff, size_t len)
{
/*当有多个kobject调用store函数 时,在这里重新获取指针,而不是
采用定义的全局变量的意义才能体现出来*/
struct my_kobject *my_kobj_test;
my_kobj_test = container_of(kobj,struct my_kobject,kobj);
printk(“===my_ktype_store===\n”);
if(0==strcmp(attr->name,”name”))
{
sscanf(buf,”%d”,&my_kobj_test->val) ;
}
else
{
printk(“should not go here\n”);
}
return len;
}
/*
struct sysfs_ops
{
ssize_t (*show)(structkobejct *, struct attribute *, char *);
ssize_t (*store)(structkobejct *, struct attribute *, char *, ssize_t);
}
*/
struct sysfs_ops my_sysfs_ops =
{
.show = my_ktype_show,
.store = my_ktype_store,
};
/*====================================================*/
struct attribute my_attr_element =
{
.name = “name”,
.mode = 0644,
};
/*
struct attribute{
char*name;//属性文件名
structmodule *owner;
mode_tmode;
}
*/
struct attribute *my_attr[] =
{
&my_attr_element,
NULL,
};
/*====================================================*/
/*
struct kobj_type {
void (*release)(struct kobject *kobj);
const struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
};
*/
struct kobj_type my_ktype =
{
.release = my_ktype_release,
.sysfs_ops = &my_sysfs_ops,
.default_attrs = my_attr,
};
struct my_kobject my_kobj; //也可以采用动态创建的方式,那样的话需
//要在kobj_type的release函数中free掉
static int __init my_kobj_init(void)
{
printk(“===my_kobj_init===\n”);
/*extern int __must_check kobject_init_and_add
(struct kobject *kobj,struct kobj_type *ktype,
struct kobject *parent,const char *fmt, ...);*/
kobject_init_and_add(&my_kobj.kobj,&my_ktype,
NULL,”kobject_test”);
return 0;
}
static void __exit my_kobj_exit(void)
{
printk(“===my_kobj_exit===\n”);
/*void kobject_del(struct kobject *kobj); */
kobject_del(&my_kobj.kobj);
/*void kobject_put(struct kobject *kobj);*/
kobject_put(&my_kobj.kobj);
}
module_init(my_kobj_init);
module_exit(my_kobj_exit);
参考文献:
[1] http://blog.csdn.net/jianchi88/article/details/6997615
[2] http://blog.chinaunix.net/uid-25550211-id-1748359.html
[3] <<LDD>>

浙公网安备 33010602011771号