裝置驅動模型之: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有關,目前在下還沒有能力講解,放到以後講解。