生活随笔
收集整理的這篇文章主要介紹了
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
?copystruct?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
?copystruct?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?{?????????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,??};?????????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);???????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_init_and_add(&obj2->kobj,?&my_type,?&obj1->kobj,?"mykobj2");?????????????????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;??}??????????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ò),歡迎將生活随笔推薦給好友。