学习linux设备与驱动有一段时间了,发现对前面的好多东西还不是很熟悉,所以借这个博客边复习边记下这些重要知识点。字符设备还是以后再慢慢添加,先从linux设备模型开始。
Kobject是组成设备模型的基本数据结构,它定义在<linux/kobject.h>中。在这个文件中,还包括了与kobject相关结构的声,当然还有一个用于操作kobject对象的函数清单。Kobject结构所能处理的任务以及它所支持的代码包括:
对象的引用计数
用于跟踪创建的内核对象的生命周期,在此引用计数的方法。
sysfs表述
在sysfs中显示的每个对象,都对应一个kobject,它被用来与内核交互并创建它的可见表述。
数据结构关联
kobject实现设备模型结构并将它们结合一起。
热插事件拔处理
当系统中的硬件被热插拔时,在kobject子系统控制下,将产生事件以通知用户空间。
kboject驱动的编写
首先来看看kobject在内核中的结构本是如何的。
struct kobject {
const char * k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject* parent;
struct kset * kset;
struct kobj_type * ktype;//记录了kobject对象的一些属性
struct dentry * entry;
wait_queue_head_t poll;
};
const char * k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject* parent;
struct kset * kset;
struct kobj_type * ktype;//记录了kobject对象的一些属性
struct dentry * entry;
wait_queue_head_t poll;
};
struct kobj_type {
void (*release)(struct kobject *);//用于释放kobject占用的资源,计数为0时调用
struct sysfs_ops* sysfs_ops;//对kobject对象属性的操作函数
struct attribute** default_attrs;//指向一个包含attribute结构数组的指针
};
void (*release)(struct kobject *);//用于释放kobject占用的资源,计数为0时调用
struct sysfs_ops* sysfs_ops;//对kobject对象属性的操作函数
struct attribute** default_attrs;//指向一个包含attribute结构数组的指针
};
struct attribute {
const char * name; //属性名字
struct module * owner; //指向模块的指针
mode_t mode; //属性的保护位,有只读和可写等属性
};
const char * name; //属性名字
struct module * owner; //指向模块的指针
mode_t mode; //属性的保护位,有只读和可写等属性
};
kobject的初始化函数和注册:
void kobject_init(struct kobject *);//初始化函数
int kobject_add(struct kobject *);//将kobject注册到Linux系统中
struct kobject * kobject_get(struct kobject * kobj);//将kobject的引用计数加1,并返回kobject结构类型的指针。
void kobject_del(struct kobject *);//删除一个kobject对象
void kobject_put(struct kobject *);//将kobject对象的引用计数减1,如果引用计数降为0,则调用release函数释放kobject对象。
以下为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_LICENSE("Dual BSD/GPL");
void obj_test_release(struct kobject *kobject);
ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf);
ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count);
struct attribute test_attr = {
.name = "kobj_config",
.mode = S_IRWXUGO,
};
static struct attribute *def_attrs[] = {
&test_attr,
NULL,
};
struct sysfs_ops obj_test_sysops =
{
.show = kobj_test_show,
.store = kobj_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 kobj_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 kobj_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 kobj_test_init()
{
printk("kboject test init.\n");
kobject_init_and_add(&kobj,&ktype,NULL,"kobject_test");
return 0;
}
static int kobj_test_exit()
{
printk("kobject test exit.\n");
kobject_del(&kobj);
return 0;
}
module_init(kobj_test_init);
module_exit(kobj_test_exit);
#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_LICENSE("Dual BSD/GPL");
void obj_test_release(struct kobject *kobject);
ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf);
ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count);
struct attribute test_attr = {
.name = "kobj_config",
.mode = S_IRWXUGO,
};
static struct attribute *def_attrs[] = {
&test_attr,
NULL,
};
struct sysfs_ops obj_test_sysops =
{
.show = kobj_test_show,
.store = kobj_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 kobj_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 kobj_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 kobj_test_init()
{
printk("kboject test init.\n");
kobject_init_and_add(&kobj,&ktype,NULL,"kobject_test");
return 0;
}
static int kobj_test_exit()
{
printk("kobject test exit.\n");
kobject_del(&kobj);
return 0;
}
module_init(kobj_test_init);
module_exit(kobj_test_exit);