前言
在上一篇文章中我们做了创建和注销kobject的实验,这篇文章以kobject_create_and_add()
和kobject_put(k_object);
为出发点详细分析一个kobject创建和注销过程中做了哪些工作。
创建kobject流程分析
函数调用关系:
根据上面的函数调用关系,我们来分析下kobject_create_and_add具体做了哪些工作。该函数主要完成两个功能:
- kobject_create:创建并初始化一个kobject结构体;
- kobject_add:将kobject添加到sysfs结构中,并在/sys/…/下创建目录。
创建与初始化
kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
使用kzmalloc申请一个结构体内存;kref_init(&kobj->kref);
将该kobject的引用计数设置为1。INIT_LIST_HEAD(&kobj->entry);
初始化链表节点,用于将该kobject加入一个kset链表。kobj->ktype = ktype;
初始化基本的kobject方法,主要包括动态释放函数dynamic_kobj_release
用于引用计数为0时自动释放kobj;kobj_attr_show
调用kobj的show函数,在用户态执行cat时调用;kobj_attr_store
调用kobj的store函数,在用户态写入时调用。
添加到sysfs
kobject_set_name_vargs(kobj, fmt, vargs);
根据传入的参数设置kobject的name,也对应/sys下看到的文件夹名。kobj->parent = parent;
根据传入的参数设置父指针。- create_dir(kobj);
创建/sys下对应的路径,这里创建路径主要涉及sysfs的知识,这里不展开,后续文章会专门分析sysfs。
注销kobject流程
在这里注销一个kobject使用的是kobject_put()
,就是讲kobj的引用计数减1,前面分析创建流程时提到kobj初始化时会将引用计数设置为1,这里调用kobject_put后会将kobj的引用计数变为0,并且同时调用kobject_release()
。因此我们主要分析kobject_release做了哪些事情。
主要函数调用关系如下;
sysfs_remove_dir(kobj);
删除/sys下的设备节点kobj_kset_leave(kobj);
将该kobj从所属的kset链表中删除。t->release(kobj);
调用kobj的release方法,默认为dynamic_kobj_release(),释放kobj的结构体内存,release方法可被重写。kfree_const(name);
释放kobj name申请的内存。kobject_put(parent);
将kobj的父kobj引用计数减1。