日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux 设备模型之 (kobject、kset 和 Subsystem)(二)

發(fā)布時(shí)間:2025/3/21 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 设备模型之 (kobject、kset 和 Subsystem)(二) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1、kobject 結(jié)構(gòu)

在Linux內(nèi)核里,kobject是組成Linux設(shè)備模型的基礎(chǔ),一個(gè)kobject對(duì)應(yīng)sysfs里的一個(gè)目錄。從面向?qū)ο蟮慕嵌葋?lái)說(shuō),kobject可以看作是所有設(shè)備對(duì)象的基類(lèi),因?yàn)镃語(yǔ)言并沒(méi)有面向?qū)ο蟮恼Z(yǔ)法,所以一般是把kobject內(nèi)嵌到其他結(jié)構(gòu)體里來(lái)實(shí)現(xiàn)類(lèi)似的作用,這里的其他結(jié)構(gòu)體可以看作是kobject的派生類(lèi)。Kobject為L(zhǎng)inux設(shè)備模型提供了很多有用的功能,比如引用計(jì)數(shù),接口抽象,父子關(guān)系等等。引用計(jì)數(shù)本質(zhì)上就是利用kref實(shí)現(xiàn)的。

另外,Linux設(shè)備模型還有一個(gè)重要的數(shù)據(jù)結(jié)構(gòu)kset。Kset本身也是一個(gè)kobject,所以它在sysfs里同樣表現(xiàn)為一個(gè)目錄,但它和kobject的不同之處在于kset可以看作是一個(gè)容器,如果你把它類(lèi)比為C++里的容器類(lèi)如list也無(wú)不可。Kset之所以能作為容器來(lái)使用,其內(nèi)部正是內(nèi)嵌了一個(gè)雙向鏈表結(jié)構(gòu)struct list_head。

kobject 在內(nèi)核中的描述

[cpp]?view plain?copy
  • struct?kobject?{??
  • ????const?char??????*name;??
  • ????struct?list_head????entry;??
  • ????struct?kobject??????*parent;??
  • ????struct?kset?????*kset;??
  • ????struct?kobj_type????*ktype;??
  • ????struct?sysfs_dirent?*sd;??
  • ????struct?kref?????kref;??
  • ????unsigned?int?state_initialized:1;??
  • ????unsigned?int?state_in_sysfs:1;??
  • ????unsigned?int?state_add_uevent_sent:1;??
  • ????unsigned?int?state_remove_uevent_sent:1;??
  • ????unsigned?int?uevent_suppress:1;??
  • };??

  • 內(nèi)核里的設(shè)備之間是以樹(shù)狀形式組織的,在這種組織架構(gòu)里比較靠上層的節(jié)點(diǎn)可以看作是下層節(jié)點(diǎn)的父節(jié)點(diǎn),反映到sysfs里就是上級(jí)目錄和下級(jí)目錄之間的關(guān)系, 在內(nèi)核里,正是kobject幫助我們實(shí)現(xiàn)這種父子關(guān)系 。在kobject的定義里,name表示的是kobject在sysfs中的名字;指針parent用來(lái)指向kobject的父對(duì)象;Kref大家應(yīng)該比較熟悉了,kobject通過(guò)它來(lái)實(shí)現(xiàn)引用計(jì)數(shù);Kset指針用來(lái)指向這個(gè)kobject所屬的kset,下文會(huì)再詳細(xì)描述kset的用法;對(duì)于ktype,如果只是望文生義的話(huà),應(yīng)該是用來(lái)描述kobject的類(lèi)型信息。Ktype的定義如下:

    [cpp]?view plain?copy
  • struct?kobj_type?{??
  • ????void?(*release)(struct?kobject?*kobj);??
  • ????const?struct?sysfs_ops?*sysfs_ops;??
  • ????struct?attribute?**default_attrs;??
  • };??
  • 函數(shù)指針release是給kref使用的, 當(dāng)引用計(jì)數(shù)為0這個(gè)指針指向的函數(shù)會(huì)被調(diào)用來(lái)釋放內(nèi)存 。sysfs_ops和attribute是做什么用的呢?前文里提到,一個(gè)kobject對(duì)應(yīng)sysfs里的一個(gè)目錄, 而目錄下的文件就是由sysfs_ops和attribute來(lái)實(shí)現(xiàn)的,其中,attribute定義了kobject的屬性,在sysfs里對(duì)應(yīng)一個(gè)文件,sysfs_ops用來(lái)定義讀寫(xiě)這個(gè)文件的方法。 Ktype里的attribute是默認(rèn)的屬性,另外也可以使用更加靈活的手段,本文的重點(diǎn)還是放在default attribute。
    [cpp]?view plain?copy
  • #include?<linux/kernel.h>??
  • #include?<linux/module.h>??
  • #include?<linux/slab.h>??
  • #include?<linux/kobject.h>??
  • ??
  • struct?my_kobj?{???//內(nèi)嵌kobject的結(jié)構(gòu)??
  • ????int?val;??
  • ????struct?kobject?kobj;??
  • };??
  • ??
  • struct?my_kobj?*obj1,?*obj2;??
  • struct?kobj_type?my_type;??
  • ??
  • struct?attribute?name_attr?=?{??
  • ????.name?=?"name",?//文件名??
  • ????.mode?=?0444,??//指定文件的訪問(wèn)權(quán)限??
  • };??
  • ??
  • struct?attribute?val_attr?=?{??
  • ????.name?=?"val",?//文件名??
  • ????.mode?=?0666,?//指定文件的訪問(wèn)權(quán)限??
  • };??
  • ??
  • struct?attribute?*my_attrs[]?=?{??
  • ????&name_attr,???
  • ????&val_attr,??
  • ????NULL,??
  • };??
  • ??
  • /*?
  • 結(jié)構(gòu)體struct?attribute里的name變量用來(lái)指定文件名,mode變量用來(lái)指定文件的訪問(wèn)權(quán)限。?
  • 這里需要著重指出的是,數(shù)組my_attrs的最后一項(xiàng)一定要賦為NULL,否則會(huì)造成內(nèi)核oops。?
  • */??
  • ssize_t?my_show(struct?kobject?*kobj,?struct?attribute?*attr,?char?*buffer)??
  • {??
  • ????struct?my_kobj?*obj?=?container_of(kobj,?struct?my_kobj,?kobj);??
  • ????ssize_t?count?=?0;??
  • ??
  • ????if?(strcmp(attr->name,?"name")?==?0)?{??
  • ????????count?=?sprintf(buffer,?"%s\n",?kobject_name(kobj));??
  • ????}?else?if?(strcmp(attr->name,?"val")?==?0)?{??
  • ????????count?=?sprintf(buffer,?"%d\n",?obj->val);??
  • ????}??
  • ??
  • ????return?count;??
  • }??
  • ??
  • ssize_t?my_store(struct?kobject?*kobj,?struct?attribute?*attr,?const?char?*buffer,?size_t?size)??
  • {??
  • ????struct?my_kobj?*obj?=?container_of(kobj,?struct?my_kobj,?kobj);??
  • ??
  • ????if?(strcmp(attr->name,?"val")?==?0)?{??
  • ????????sscanf(buffer,?"%d",?&obj->val);??
  • ????}??
  • ??
  • ????return?size;??
  • }??
  • ??
  • struct?sysfs_ops?my_sysfsops?=?{??
  • ????.show?=?my_show,??
  • ????.store?=?my_store,??
  • };??
  • ??
  • void?obj_release(struct?kobject?*kobj)??
  • {??
  • ????struct?my_kobj?*obj?=?container_of(kobj,?struct?my_kobj,?kobj);??
  • ????printk(KERN_INFO?"obj_release?%s\n",?kobject_name(&obj->kobj));??
  • ????kfree(obj);??
  • }??
  • ??
  • static?int?__init?mykobj_init(void)??
  • {??
  • ????printk(KERN_INFO?"mykobj_init\n");??
  • ??
  • ????obj1?=?kzalloc(sizeof(struct?my_kobj),?GFP_KERNEL);?//分配obj1和obj2并賦值??
  • ????if?(!obj1)?{??
  • ????????return?-ENOMEM;??
  • ????}??
  • ????obj1->val?=?1;??
  • ??
  • ????obj2?=?kzalloc(sizeof(struct?my_kobj),?GFP_KERNEL);??
  • ????if?(!obj2)?{??
  • ????????kfree(obj1);??
  • ????????return?-ENOMEM;??
  • ????}??
  • ????obj2->val?=?2;??
  • ??
  • ????my_type.release?=?obj_release;??
  • ????my_type.default_attrs?=?my_attrs;??
  • ????my_type.sysfs_ops?=?&my_sysfsops;??
  • ??
  • ????kobject_init_and_add(&obj1->kobj,?&my_type,?NULL,?"mykobj1");?/*函數(shù)來(lái)初始化kobject并把它加入到設(shè)備模型的體系架構(gòu)*/??
  • ????kobject_init_and_add(&obj2->kobj,?&my_type,?&obj1->kobj,?"mykobj2");??
  • /*?
  • ????kobject_init用來(lái)初始化kobject結(jié)構(gòu),kobject_add用來(lái)把kobj加入到設(shè)備模型之中。?
  • ????在實(shí)作中,我們先對(duì)obj1進(jìn)行初始化和添加的動(dòng)作,調(diào)用參數(shù)里,parent被賦為NULL,表示obj1沒(méi)有父對(duì)象,反映到sysfs里,?
  • ????my_kobj1的目錄會(huì)出現(xiàn)在/sys下,obj2的父對(duì)象設(shè)定為obj1,那么my_kobj2的目錄會(huì)出現(xiàn)在/sys/my_kobj1下面。?
  • ????前面提到,kobject也提供了引用計(jì)數(shù)的功能,雖然本質(zhì)上是利用kref,但也提供了另外的接口供用戶(hù)使用。?
  • ????kobject_init_and_add和kobject_init這兩個(gè)函數(shù)被調(diào)用后,kobj的引用計(jì)數(shù)會(huì)初始化為1,?
  • ????所以在module_exit時(shí)要記得用kobject_put來(lái)釋放引用計(jì)數(shù)。?
  • */????
  • ????return?0;??
  • }??
  • ??
  • static?void?__exit?mykobj_exit(void)??
  • {??
  • ????printk(KERN_INFO?"mykobj_exit\n");??
  • ??
  • ????kobject_del(&obj2->kobj);?/*先子對(duì)象,后父對(duì)象*/??
  • ????kobject_put(&obj2->kobj);??
  • ??????
  • ????kobject_del(&obj1->kobj);??
  • ????kobject_put(&obj1->kobj);??
  • ??
  • ????return;??
  • }??
  • /*?
  • kobject_del的作用是把kobject從設(shè)備模型的那棵樹(shù)里摘掉,同時(shí)sysfs里相應(yīng)的目錄也會(huì)刪除。?
  • 這里需要指出的是,釋放的順序應(yīng)該是先子對(duì)象,后父對(duì)象。?
  • 因?yàn)閗object_init_and_add和kobject_add這兩個(gè)函數(shù)會(huì)調(diào)用kobject_get來(lái)增加父對(duì)象的引用計(jì)數(shù),?
  • 所以kobject_del需要調(diào)用kobject_put來(lái)減少父對(duì)象的引用計(jì)數(shù)。在本例中,如果先通過(guò)kobject_put來(lái)釋放obj1,?
  • 那kobject_del(&obj2->kobj)就會(huì)出現(xiàn)內(nèi)存錯(cuò)誤。?
  • */??
  • module_init(mykobj_init);??
  • module_exit(mykobj_exit);??
  • ??
  • MODULE_LICENSE("GPL"); ?
  • 總結(jié)

    以上是生活随笔為你收集整理的Linux 设备模型之 (kobject、kset 和 Subsystem)(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。