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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

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

1、kobject 結構

在Linux內核里,kobject是組成Linux設備模型的基礎,一個kobject對應sysfs里的一個目錄。從面向對象的角度來說,kobject可以看作是所有設備對象的基類,因為C語言并沒有面向對象的語法,所以一般是把kobject內嵌到其他結構體里來實現類似的作用,這里的其他結構體可以看作是kobject的派生類。Kobject為Linux設備模型提供了很多有用的功能,比如引用計數,接口抽象,父子關系等等。引用計數本質上就是利用kref實現的。

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

kobject 在內核中的描述

[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;??
  • };??

  • 內核里的設備之間是以樹狀形式組織的,在這種組織架構里比較靠上層的節點可以看作是下層節點的父節點,反映到sysfs里就是上級目錄和下級目錄之間的關系, 在內核里,正是kobject幫助我們實現這種父子關系 。在kobject的定義里,name表示的是kobject在sysfs中的名字;指針parent用來指向kobject的父對象;Kref大家應該比較熟悉了,kobject通過它來實現引用計數;Kset指針用來指向這個kobject所屬的kset,下文會再詳細描述kset的用法;對于ktype,如果只是望文生義的話,應該是用來描述kobject的類型信息。Ktype的定義如下:

    [cpp]?view plain?copy
  • struct?kobj_type?{??
  • ????void?(*release)(struct?kobject?*kobj);??
  • ????const?struct?sysfs_ops?*sysfs_ops;??
  • ????struct?attribute?**default_attrs;??
  • };??
  • 函數指針release是給kref使用的, 當引用計數為0這個指針指向的函數會被調用來釋放內存 。sysfs_ops和attribute是做什么用的呢?前文里提到,一個kobject對應sysfs里的一個目錄, 而目錄下的文件就是由sysfs_ops和attribute來實現的,其中,attribute定義了kobject的屬性,在sysfs里對應一個文件,sysfs_ops用來定義讀寫這個文件的方法。 Ktype里的attribute是默認的屬性,另外也可以使用更加靈活的手段,本文的重點還是放在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?{???//內嵌kobject的結構??
  • ????int?val;??
  • ????struct?kobject?kobj;??
  • };??
  • ??
  • struct?my_kobj?*obj1,?*obj2;??
  • struct?kobj_type?my_type;??
  • ??
  • struct?attribute?name_attr?=?{??
  • ????.name?=?"name",?//文件名??
  • ????.mode?=?0444,??//指定文件的訪問權限??
  • };??
  • ??
  • struct?attribute?val_attr?=?{??
  • ????.name?=?"val",?//文件名??
  • ????.mode?=?0666,?//指定文件的訪問權限??
  • };??
  • ??
  • struct?attribute?*my_attrs[]?=?{??
  • ????&name_attr,???
  • ????&val_attr,??
  • ????NULL,??
  • };??
  • ??
  • /*?
  • 結構體struct?attribute里的name變量用來指定文件名,mode變量用來指定文件的訪問權限。?
  • 這里需要著重指出的是,數組my_attrs的最后一項一定要賦為NULL,否則會造成內核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");?/*函數來初始化kobject并把它加入到設備模型的體系架構*/??
  • ????kobject_init_and_add(&obj2->kobj,?&my_type,?&obj1->kobj,?"mykobj2");??
  • /*?
  • ????kobject_init用來初始化kobject結構,kobject_add用來把kobj加入到設備模型之中。?
  • ????在實作中,我們先對obj1進行初始化和添加的動作,調用參數里,parent被賦為NULL,表示obj1沒有父對象,反映到sysfs里,?
  • ????my_kobj1的目錄會出現在/sys下,obj2的父對象設定為obj1,那么my_kobj2的目錄會出現在/sys/my_kobj1下面。?
  • ????前面提到,kobject也提供了引用計數的功能,雖然本質上是利用kref,但也提供了另外的接口供用戶使用。?
  • ????kobject_init_and_add和kobject_init這兩個函數被調用后,kobj的引用計數會初始化為1,?
  • ????所以在module_exit時要記得用kobject_put來釋放引用計數。?
  • */????
  • ????return?0;??
  • }??
  • ??
  • static?void?__exit?mykobj_exit(void)??
  • {??
  • ????printk(KERN_INFO?"mykobj_exit\n");??
  • ??
  • ????kobject_del(&obj2->kobj);?/*先子對象,后父對象*/??
  • ????kobject_put(&obj2->kobj);??
  • ??????
  • ????kobject_del(&obj1->kobj);??
  • ????kobject_put(&obj1->kobj);??
  • ??
  • ????return;??
  • }??
  • /*?
  • kobject_del的作用是把kobject從設備模型的那棵樹里摘掉,同時sysfs里相應的目錄也會刪除。?
  • 這里需要指出的是,釋放的順序應該是先子對象,后父對象。?
  • 因為kobject_init_and_add和kobject_add這兩個函數會調用kobject_get來增加父對象的引用計數,?
  • 所以kobject_del需要調用kobject_put來減少父對象的引用計數。在本例中,如果先通過kobject_put來釋放obj1,?
  • 那kobject_del(&obj2->kobj)就會出現內存錯誤。?
  • */??
  • module_init(mykobj_init);??
  • module_exit(mykobj_exit);??
  • ??
  • MODULE_LICENSE("GPL"); ?
  • 總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。