關於linux裝置模型kobject,kset,ktype

來源:互聯網
上載者:User

--------------------------------------------------------
本文系本站原創,歡迎轉載!
轉載請註明出處:http://blog.csdn.net/gdt_a20
--------------------------------------------------------

 

一、sysfs檔案系統下的每個目錄對應於一個kobj,kset是kobj的封裝,內嵌了一個kobj,其代表kset自身,ktype代表屬性操作集,但由於通用性,因此把ktype單獨剝離出來,kobj,kset,ktype成為了各個驅動模型最底層的關聯元素,並由此形成了sys下的各種拓撲結構。

二、關於kobject

      首先看一下kobject的原型

            struct kobject {<br />const char*name; //名字<br />struct list_headentry; //串連到kset建立階層<br />struct kobject*parent; //指向父節點,物件導向的層次架構<br />struct kset*kset;<br />struct kobj_type*ktype; //屬性檔案<br />struct sysfs_dirent*sd;<br />struct krefkref; //引用計數<br />unsigned int state_initialized:1; //初始化狀態...<br />unsigned int state_in_sysfs:1;<br />unsigned int state_add_uevent_sent:1;<br />unsigned int state_remove_uevent_sent:1;<br />unsigned int uevent_suppress:1;<br />};

   分析一下kobject的初始化過程

   初始化函數為

           ---int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, //參數為kobject和屬性結構體<br /> struct kobject *parent, const char *fmt, ...)<br />{<br />va_list args;<br />int retval;<br />kobject_init(kobj, ktype);<br />va_start(args, fmt);<br />retval = kobject_add_varg(kobj, parent, fmt, args);<br />va_end(args);<br />return retval;<br />}<br />---void kobject_init(struct kobject *kobj, struct kobj_type *ktype)<br />{<br />char *err_str;<br />if (!kobj) { //kobj為NULL錯誤退出<br />err_str = "invalid kobject pointer!";<br />goto error;<br />}<br />if (!ktype) { //ktype為NULL錯誤退出<br />err_str = "must have a ktype to be initialized properly!/n";<br />goto error;<br />}<br />if (kobj->state_initialized) { //如果初始化狀態為1報錯<br />/* do not error out as sometimes we can recover */<br />printk(KERN_ERR "kobject (%p): tried to init an initialized "<br /> "object, something is seriously wrong./n", kobj);<br />dump_stack();<br />}<br />kobject_init_internal(kobj); //初始化kobj<br />kobj->ktype = ktype; //關聯obj和ktype<br />return;<br />error:<br />printk(KERN_ERR "kobject (%p): %s/n", kobj, err_str);<br />dump_stack();<br />}<br />-------static void kobject_init_internal(struct kobject *kobj)<br />{<br />if (!kobj)<br />return;<br />kref_init(&kobj->kref); //計數變成1<br />INIT_LIST_HEAD(&kobj->entry); //都指向自己,prev和next<br />kobj->state_in_sysfs = 0;<br />kobj->state_add_uevent_sent = 0;<br />kobj->state_remove_uevent_sent = 0;<br />kobj->state_initialized = 1;<br />}<br />-------static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,<br /> const char *fmt, va_list vargs)<br />{<br />int retval;<br />retval = kobject_set_name_vargs(kobj, fmt, vargs); //設定名字,名字中不能有“/”<br />if (retval) {<br />printk(KERN_ERR "kobject: can not set name properly!/n");<br />return retval;<br />}<br />kobj->parent = parent; //設定parent,其父節點<br />return kobject_add_internal(kobj);<br />}<br />----static int kobject_add_internal(struct kobject *kobj)<br />{<br />int error = 0;<br />struct kobject *parent;<br />if (!kobj)<br />return -ENOENT;<br />if (!kobj->name || !kobj->name[0]) { //名字不可為空<br />WARN(1, "kobject: (%p): attempted to be registered with empty "<br /> "name!/n", kobj);<br />return -EINVAL;<br />}<br />parent = kobject_get(kobj->parent); //如果parent為真,則增加kobj->kref計數,也就是父節點的引用計數<br />/* join kset if set, use it as parent if we do not already have one */<br />if (kobj->kset) {<br />if (!parent)<br />parent = kobject_get(&kobj->kset->kobj); //如果kobj-parent父節點為NULL那麼就用kobj->kset->kobj<br /> // 作其父節點,並增加其引用計數<br />kobj_kset_join(kobj); //把kobj的entry成員添加到kobj->kset>list的尾部,現在的層次就是<br />kobj->parent = parent; //kobj->kset->list指向kobj->parent<br />} // ->parent 指向kset->kobj<br />pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'/n",<br /> kobject_name(kobj), kobj, __func__,<br /> parent ? kobject_name(parent) : "<NULL>",<br /> kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");<br />error = create_dir(kobj); //利用kobj建立目錄和屬性檔案,其中會判斷,如果parent為NULL那麼就在sysfs_root下建立<br />if (error) {<br />kobj_kset_leave(kobj);<br />kobject_put(parent);<br />kobj->parent = NULL;<br />/* be noisy on error issues */<br />if (error == -EEXIST)<br />printk(KERN_ERR "%s failed for %s with "<br /> "-EEXIST, don't try to register things with "<br /> "the same name in the same directory./n",<br /> __func__, kobject_name(kobj));<br />else<br />printk(KERN_ERR "%s failed for %s (%d)/n",<br /> __func__, kobject_name(kobj), error);<br />dump_stack();<br />} else<br />kobj->state_in_sysfs = 1;<br />return error;<br />}<br />---static int create_dir(struct kobject *kobj)<br />{<br />int error = 0;<br />if (kobject_name(kobj)) {<br />error = sysfs_create_dir(kobj); //建立目錄<br />if (!error) {<br />error = populate_dir(kobj); //建立屬性檔案<br />if (error)<br />sysfs_remove_dir(kobj);<br />}<br />}<br />return error;<br />}

 

三、關於 kset

      首先看一下kset的原型

          struct kset {<br />struct list_head list; //串連著他下面的kobj成員,與kobj-entry關聯<br />spinlock_t list_lock;<br />struct kobject kobj; //代表kset自己<br />const struct kset_uevent_ops *uevent_ops;<br />};

       再來看一下kset的初始化操作,kset表現為更進階一點的kobj,其初始化操作仍然是圍繞其內部的kobj展開的。

 

          struct kset *kset_create_and_add(const char *name,<br /> const struct kset_uevent_ops *uevent_ops,<br /> struct kobject *parent_kobj)<br />{<br />struct kset *kset;<br />int error;<br />kset = kset_create(name, uevent_ops, parent_kobj); //建立kset,關聯操作函數和其父節點<br />if (!kset)<br />return NULL;<br />error = kset_register(kset);<br />if (error) {<br />kfree(kset);<br />return NULL;<br />}<br />return kset;<br />}<br />---static struct kset *kset_create(const char *name,<br />const struct kset_uevent_ops *uevent_ops,<br />struct kobject *parent_kobj)<br />{<br />struct kset *kset;<br />int retval;<br />kset = kzalloc(sizeof(*kset), GFP_KERNEL); //申請結構體記憶體<br />if (!kset)<br />return NULL;<br />retval = kobject_set_name(&kset->kobj, name); //設定名字<br />if (retval) {<br />kfree(kset);<br />return NULL;<br />}<br />kset->uevent_ops = uevent_ops; //關聯操作函數<br />kset->kobj.parent = parent_kobj; //關聯父節點<br />/*<br /> * The kobject of this kset will have a type of kset_ktype and belong to<br /> * no kset itself. That way we can properly free it when it is<br /> * finished being used.<br /> */<br />kset->kobj.ktype = &kset_ktype; //關聯屬性檔案<br />kset->kobj.kset = NULL;<br />return kset;<br />}<br />----int kset_register(struct kset *k)<br />{<br />int err;<br />if (!k)<br />return -EINVAL;<br />kset_init(k);<br />err = kobject_add_internal(&k->kobj); //調用kobj操作函數<br />if (err)<br />return err;<br />kobject_uevent(&k->kobj, KOBJ_ADD);<br />return 0;<br />}<br />----void kset_init(struct kset *k)<br />{<br />kobject_init_internal(&k->kobj); //調用kobj操作函數<br />INIT_LIST_HEAD(&k->list);<br />spin_lock_init(&k->list_lock);<br />}

四、上面給出了kobj,kset的初始化過程,以及相互產生關聯的關鍵點,下面給出整體的一個流程圖:

        

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.