设备驱动模型之:kobject,kset,ktype(六)

本篇博客介绍kset与kobject/kset之间的关系,好了,废话不多说,直接上ktype的结构体:

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);
};

从此结构体可以看出,前两个结构体成员均为函数指针或者由函数指针组成的结构体,先讲他们的作用吧;
**

release指针

**
release函数为kobject或者kset->kobj的release操作,主要作用是对于内存的申请和释放操作,对于使用kmalloc向内核中申请内存的操作,可以调用此函数进行手动释放或者自动释放;
为什么叫做自动释放呢?因为在kobject或者kset中的kobject_put或者kset_put操作中有调用kobject->ktype->release()函数,如下:

void kobject_put(struct kobject *kobj)
{
        if (kobj) {
                if (!kobj->state_initialized)
                        WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
                               "initialized, yet kobject_put() is being "
                               "called.\n", kobject_name(kobj), kobj);
                kref_put(&kobj->kref, kobject_release);
        }
}

kref_put函数如下:
int kref_put(struct kref *kref, void (*release)(struct kref *kref))
{
        WARN_ON(release == NULL);
        WARN_ON(release == (void (*)(struct kref *))kfree);

        if (atomic_dec_and_test(&kref->refcount)) {
                release(kref);
                return 1;
        }
        return 0;
}

有上述函数可见在函数kref_put函数中会执行release操作,这个release的典型应用是在kset_create_and_add操作,回想一下在kset_create_add_add操作里面调用了kset_create函数,并且在kset_create函数里面执行了什么?执行了kset->kobj.ktype = &kset_ktype;赋值操作,在kset_ktype里面有默认的release操作,这个操作就是对于kset的一个kfree操作,也就是在kset_create_and_add函数里面不需要手动释放创建好的kset指针,只需要调用kset_unregister指针就可以释放kset指针;

**

sysfs_ops指针

**
sysfs_ops指针的结构体原型如下:

struct sysfs_ops {
        ssize_t (*show)(struct kobject *, struct attribute *,char *);
        ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
};

可以看出其只有两个函数指针,这两个函数指针怎么使用呢?
先不管两个指针怎么使用的问题,先管两个指针什么时候使用的问题自然而然就有两个指针怎么使用的答案了,那两个指针什么时候使用呢?答案是在kobject->kset->default_attrs对应的文件读写的时候使用,这个特性与sysfs相关,现在知识了解即可,如果有兴趣可以追一下这两个函数使用的时机就会一目了然了。
**

default_attrs指针

**
有人问了default_attrs明明是一个二级指针,为什么你直接叫它指针呢?因为在default_attrs定义过程中它是以指针的形式使用的,他指向的是一个struct attribute *的一个数组,在使用过程中也是以指针数组的形式去使用的,如下:

static int populate_dir(struct kobject *kobj)
{
        struct kobj_type *t = get_ktype(kobj);
        struct attribute *attr;
        int error = 0;
        int i;
        
        if (t && t->default_attrs) {
        	以指针数组的形式使用的
                for (i = 0; (attr = t->default_attrs[i]) != NULL; i++) {
                        error = sysfs_create_file(kobj, attr);
                        if (error)
                                break;
                }
        }
        return error;
}

从上述可以看出default_attrs的一个特性:就是在kobject->name目录下创建ARRAY_SIZE(default_attrs)个文件,每一个文件的操作对应着ktype->sysfs_ops操作,每一个文件属性存在于struct attribute操作。
**

剩下的结构体变量

**
在以上分析中可以看到对于ktype中的主要结构体做了比较详尽的分析,还有两个结构体变量:

        const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
        const void *(*namespace)(struct kobject *kobj);

此两个结构体变量于namespace有关,目前在下还没有能力讲解,放到以后讲解。

猜你喜欢

转载自blog.csdn.net/weixin_37867857/article/details/84841697