现在的位置: 首页 > 综合 > 正文

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

2013年09月03日 ⁄ 综合 ⁄ 共 5858字 ⁄ 字号 评论关闭

设备模型第一层:

 

一、重要结构体概述:

 

1kobject对象:

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-1kobj_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);

};

 

2kset对象:

struct kset {

struct list_head list; //对象集合的链表头

spinlock_t list_lock; //自旋锁

struct kobject kobj; //嵌入对象,也即基类

const struct kset_uevent_ops *uevent_ops; //用于事件操作

};

 

2-1kset_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);

};

二、重要的常量数据:

 

1static const struct kset_uevent_ops device_uevent_ops = {

.filter = dev_uevent_filter,

.name = dev_uevent_name,

.uevent = dev_uevent,

};

2static struct kobj_type kset_ktype = {

.sysfs_ops = &kobj_sysfs_ops,

.release = kset_release,

};

3static struct kobj_type dynamic_kobj_ktype = {

.release = dynamic_kobj_release,

.sysfs_ops = &kobj_sysfs_ops,

};

4const 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;

}

抱歉!评论已关闭.