您的位置:首页 > 运维架构 > Linux

linux内核学习(16)设备模型第一层

2011-01-09 17:08 411 查看
设备模型第一层:


一、重要结构体概述:


1、kobject对象:
struct kobject {
const char *name; //名字
struct list_head entry; //作为父对象的链表节点
struct kobject *parent; //父对象
struct kset *kset; //属于哪个对象集合
struct kobj_type *ktype; //对象类型
struct sysfs_dirent *sd; //sysfs文件系统目录
struct kref kref; //引用
unsigned int state_initialized:1; //已经初始化
unsigned int state_in_sysfs:1; //已经加入sysfs文件系统
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int uevent_suppress:1;
};


1-1、kobj_type对象类型:
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);
};


2、kset对象:
struct kset {
struct list_head list; //对象集合的链表头
spinlock_t list_lock; //自旋锁
struct kobject kobj; //嵌入对象,也即基类
const struct kset_uevent_ops *uevent_ops; //用于事件操作
};


2-1、kset_uevent_ops事件操作:
struct kset_uevent_ops {
int (* const filter)(struct kset *kset, struct kobject *kobj);
const char *(* const name)(struct kset *kset, struct kobject *kobj);
int (* const uevent)(struct kset *kset, struct kobject *kobj,
struct kobj_uevent_env *env);
};
二、重要的常量数据:


1、static const struct kset_uevent_ops device_uevent_ops = {
.filter = dev_uevent_filter,
.name = dev_uevent_name,
.uevent = dev_uevent,
};
2、static struct kobj_type kset_ktype = {
.sysfs_ops = &kobj_sysfs_ops,
.release = kset_release,
};
3、static struct kobj_type dynamic_kobj_ktype = {
.release = dynamic_kobj_release,
.sysfs_ops = &kobj_sysfs_ops,
};
4、const struct sysfs_ops kobj_sysfs_ops = {
.show = kobj_attr_show,
.store = kobj_attr_store,
};
;
三、重要的函数:


kobject类:
struct kobject *kobject_get(struct kobject *kobj)
{
if (kobj)
kref_get(&kobj->kref);
return kobj;
}
static void kobject_init_internal(struct kobject *kobj)
{
if (!kobj)
return;
kref_init(&kobj->kref);
INIT_LIST_HEAD(&kobj->entry);
kobj->state_in_sysfs = 0;
kobj->state_add_uevent_sent = 0;
kobj->state_remove_uevent_sent = 0;
kobj->state_initialized = 1;
}
void kobject_init(struct kobject *kobj, struct kobj_type *ktype)
{
char *err_str;


if (!kobj) {
err_str = "invalid kobject pointer!";
goto error;
}
if (!ktype) {
err_str = "must have a ktype to be initialized properly!/n";
goto error;
}
if (kobj->state_initialized) {
/* do not error out as sometimes we can recover */
printk(KERN_ERR "kobject (%p): tried to init an initialized "
"object, something is seriously wrong./n", kobj);
dump_stack();
}


kobject_init_internal(kobj);
kobj->ktype = ktype;
return;


error:
printk(KERN_ERR "kobject (%p): %s/n", kobj, err_str);
dump_stack();
}
static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,
const char *fmt, va_list vargs)
{
int retval;


retval = kobject_set_name_vargs(kobj, fmt, vargs);
if (retval) {
printk(KERN_ERR "kobject: can not set name properly!/n");
return retval;
}
kobj->parent = parent;
return kobject_add_internal(kobj);
}
int kobject_add(struct kobject *kobj, struct kobject *parent,
const char *fmt, ...)
{
va_list args;
int retval;


if (!kobj)
return -EINVAL;


if (!kobj->state_initialized) {
printk(KERN_ERR "kobject '%s' (%p): tried to add an "
"uninitialized object, something is seriously wrong./n",
kobject_name(kobj), kobj);
dump_stack();
return -EINVAL;
}
va_start(args, fmt);
retval = kobject_add_varg(kobj, parent, fmt, args);
va_end(args);


return retval;
}
static void kobj_kset_join(struct kobject *kobj)
{
if (!kobj->kset)
return;


kset_get(kobj->kset);
spin_lock(&kobj->kset->list_lock);
list_add_tail(&kobj->entry, &kobj->kset->list);
spin_unlock(&kobj->kset->list_lock);
}
static int kobject_add_internal(struct kobject *kobj)
{
int error = 0;
struct kobject *parent;


if (!kobj)
return -ENOENT;


if (!kobj->name || !kobj->name[0]) {
WARN(1, "kobject: (%p): attempted to be registered with empty "
"name!/n", kobj);
return -EINVAL;
}


parent = kobject_get(kobj->parent);


/* 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, __func__,
parent ? kobject_name(parent) : "<NULL>",
kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");


error = create_dir(kobj);
//在kobj的父对象目录里创建kobj目录
if (error) {
kobj_kset_leave(kobj);
kobject_put(parent);
kobj->parent = NULL;


/* be noisy on error issues */
if (error == -EEXIST)
printk(KERN_ERR "%s failed for %s with "
"-EEXIST, don't try to register things with "
"the same name in the same directory./n",
__func__, kobject_name(kobj));
else
printk(KERN_ERR "%s failed for %s (%d)/n",
__func__, kobject_name(kobj), error);
dump_stack();
} else
kobj->state_in_sysfs = 1;


return error;
}
struct kobject *kobject_create(void)
{
struct kobject *kobj;


kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
if (!kobj)
return NULL;


kobject_init(kobj, &dynamic_kobj_ktype);
return kobj;
}
struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
{
struct kobject *kobj;
int retval;


kobj = kobject_create();
if (!kobj)
return NULL;


retval = kobject_add(kobj, parent, "%s", name);
if (retval) {
printk(KERN_WARNING "%s: kobject_add error: %d/n",
__func__, retval);
kobject_put(kobj);
kobj = NULL;
}
return kobj;
}
kset类:
void kset_init(struct kset *k)
{
kobject_init_internal(&k->kobj);
INIT_LIST_HEAD(&k->list);
spin_lock_init(&k->list_lock);
}
static inline struct kset *kset_get(struct kset *k)
{
return k ? to_kset(kobject_get(&k->kobj)) : NULL;
}
static struct kset *kset_create(const char *name,
const struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
int retval;


kset = kzalloc(sizeof(*kset), GFP_KERNEL);
if (!kset)
return NULL;
retval = kobject_set_name(&kset->kobj, name);
if (retval) {
kfree(kset);
return NULL;
}
kset->uevent_ops = uevent_ops;
kset->kobj.parent = parent_kobj;


/*
* The kobject of this kset will have a type of kset_ktype and belong to
* no kset itself. That way we can properly free it when it is
* finished being used.
*/
kset->kobj.ktype = &kset_ktype;
kset->kobj.kset = NULL;


return kset;
}
int kset_register(struct kset *k)
{
int err;


if (!k)
return -EINVAL;


kset_init(k);
err = kobject_add_internal(&k->kobj);
if (err)
return err;
kobject_uevent(&k->kobj, KOBJ_ADD);
return 0;
}
struct kset *kset_create_and_add(const char *name,
const struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
int error;


kset = kset_create(name, uevent_ops, parent_kobj);
if (!kset)
return NULL;
error = kset_register(kset);
if (error) {
kfree(kset);
return NULL;
}
return kset;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: