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

    技术2022-06-28  47

    设备模型第一层:

     

    一、重要结构体概述:

     

    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;

    }


    最新回复(0)