Linux设备驱动之Kobject、Kset
LDD3中說,Kobject的作用為:
??? 1、sysfs 表述:在 sysfs 中出現(xiàn)的每個(gè)對象都對應(yīng)一個(gè) kobject, 它和內(nèi)核交互來創(chuàng)建它的可見表述。
??? 2、熱插拔事件處理 :kobject 子系統(tǒng)將產(chǎn)生的熱插拔事件通知用戶空間。
? ? 3、數(shù)據(jù)結(jié)構(gòu)關(guān)聯(lián):整體來看, 設(shè)備模型是一個(gè)極端復(fù)雜的數(shù)據(jù)結(jié)構(gòu),通過其間的大量鏈接而構(gòu)成一個(gè)多層次的體系結(jié)構(gòu)。kobject 實(shí)現(xiàn)了該結(jié)構(gòu)并將其聚合在一起。?
? ? 此篇文章,只分析第一條,kobject 與 kset sysfs 之間的關(guān)系。剩下的兩條將在后續(xù)的兩篇文章中分析
? ??
首先,什么是 kobject ,它也不過是內(nèi)核里的一個(gè)結(jié)構(gòu)體而已
? ??struct kobject {
??? ? ??const char??????? *name;
??? ? ??struct list_head??? entry;
??? ? ??struct kobject??????? *parent;
??? ? ??struct kset??????? *kset;
??? ? ??struct kobj_type??? *ktype;
??? ? ??......// 省略一些暫時(shí)不想看到的東西
? ??};
那么,這個(gè)結(jié)構(gòu)體有何特殊之處呢?
??? ? ??每一個(gè) kobject 對應(yīng) 文件系統(tǒng) /sys 里的一個(gè) 目錄,目錄的名字就是結(jié)構(gòu)體中的 name
???
什么又是 kset ,kset 也是個(gè)結(jié)構(gòu)體而已
? ??struct kset {
??? ? ??struct list_head list;???
??? ? ??struct kobject kobj;???
??? ? ??struct kset_uevent_ops *uevent_ops;
??? ? ??spinlock_t list_lock;
? ??};
? ??我們前面說了,每一個(gè) kobj 對應(yīng) 文件系統(tǒng) /sys 里的一個(gè) 目錄,那么每一個(gè) kset 都包含了一個(gè) kobj,那樣的話,kset也對應(yīng)于 /sys 里的一個(gè) 目錄
? ??簡單來說,kset 與 kobj 都是目錄,既然是目錄,那么在就是一個(gè)樹狀結(jié)構(gòu),每一個(gè)目錄都將有一個(gè) 父節(jié)點(diǎn),
? ??? ??在kset中使用kset.kobj->parent 指定
? ??? ??在kboject中使用? kobj->parent 指定
? ??顯然,整個(gè)樹狀目錄結(jié)構(gòu),都是通過kobj來構(gòu)建的,只不過有些kobj嵌在Kset里,分析目錄結(jié)構(gòu)時(shí)把kset當(dāng)成一個(gè)普通的kobj會(huì)好理解很多。
那么kset 有何特殊之處呢?
? ? 我們可以看到 kset 結(jié)構(gòu)中有一個(gè)鏈表,它目錄下的 一些相同類型的kobj會(huì)在創(chuàng)建時(shí)鏈入鏈表,也就是說Kset是一些kobj的集合。? ??
? ??干說還是比較抽象的,那么我們就來看看 /sys 目錄底下的這些東西,哪些是kset 哪些是kobj 結(jié)構(gòu)又是怎樣的。
? ??看過代碼的應(yīng)該知道,想要在/sys 目錄下創(chuàng)建 目錄,那就要 構(gòu)造 kset 或者 kobj 設(shè)置并注冊。
? ??對于kobject:
??? ? ??kobject_create_and_add
??? ? ??kobject_init_and_add
? ??對于kset:
??? ? ??kset_create_and_add
??? 我在這3個(gè)函數(shù)中增加了prink打印語句,打印內(nèi)核創(chuàng)建的每一個(gè) kobj 或者 kset 的名字,以及父節(jié)點(diǎn)的名字,甚至它指向的kset的kobj的名字。
???
??? 原本我以為,較高層次的目錄會(huì)是kset,因?yàn)樗莻€(gè)集合嘛,然而并不全是。
??? ? ??the kset name is devices,no parent
??????? ? ??the kset name is system,parent's name is devices
??????? ? ??the kobject name is virtual,parent's name is devices???
??? ? ??the kset name is bus,no parent
??? ? ??the kset name is class,no parent
??? ? ??the kset name is module,no parent
??? ? ??the kobject name is fs,no parent
???? ?? the kobject name is dev,no parent
??????? ? ??the kobject name is block,parent's name is dev
??????? ? ??the kobject name is char,parent's name is dev???????
??? ? ??the kobject name is firmware,no parent
??? ? ??the kobject name is kernel,no parent
??????? ? ??the kset name is slab,parent's name is kernel
??? ? ??the kobject name is block,no parent
??? 寫著no parent的,在/sys/目錄下可以找到它們,對于devices、bus、class、module它們是kset
??????????????????????????????????????????????? ? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ??對于fs、dev、firmware、kernel、block 它們是 kobj
而且,我們還可以發(fā)現(xiàn)
??? 1、??? kset 底下可以放 kset (但是無法鏈入鏈表,分析代碼時(shí)會(huì)知道)
????????the kset name is devices,no parent
??????????? ? ??the kset name is system,parent's name is devices
??? 2、??? kset 底下可以放 kobj (可以鏈入鏈表,也可以不鏈入)
??????? the kset name is devices,no parent
??????????? the kobject name is virtual,parent's name is devices
??? 3、 kobject 底下可以放 kset (顯然沒鏈表的概念了)
??????? the kobject name is kernel,no parent
??????????? the kset name is slab,parent's name is kernel
??? 4、 kobj 底下放 kobj (同樣沒有鏈表的概念)
??????? the kobject name is dev,no parent
??????????? the kobject name is block,parent's name is dev
???? 如下圖:黃色代表Kset 藍(lán)色代表Kobject
???????
? ??那么,至此我們對kset kobj它們之間的聯(lián)系就應(yīng)該有一個(gè)比較淺顯的認(rèn)識(shí)了。
------------------------------------------------------------------------------------------------------------------------------------------------------
下面來分析代碼,進(jìn)一步摸索,先把圖貼上來,虛線表示可能的其它一些連接情況。
---------------------------------------------------------------------------------------------------------------------------------------------------------------
? ??struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
? ??? ??{
? ? ? ? ? ??? ??struct kobject *kobj;
? ? ? ? ? ? ? ? kobj = kobject_create();
? ? ? ? ? ? ? ? retval = kobject_add(kobj, parent, "%s", name);
? ? ? ? ? ? ? ? return kobj;
? ? ? ? }
?
? ??kobject_create_and_add
? ? ? ??kobject_create??????? // kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
????????? ??kobject_init ? ? ? ? ? ? ?// kobj->ktype = ktype;
?????????? ?kobject_init_internal??? // kref_init(&kobj->kref);
? ? ? ? kobject_add
? ? ? ? ? ? kobject_add_varg??? // retval = kobject_set_name_vargs(kobj, fmt, vargs); // kobj->parent = parent;
? ? ? ? ? ? kobject_add_internal
? ? ? ? ? ? if (kobj->kset) {??? // kobj->kset == NULL 不執(zhí)行
? ? ? ? ? ? ? ??if (!parent)
? ? ? ? ? ? ? ? ? ??parent = kobject_get(&kobj->kset->kobj);
? ? ? ? ? ? ? ? ? ? kobj_kset_join(kobj);
? ? ? ? ? ? ? ? ? ? kobj->parent = parent;
? ? ? ? ? ? }
? ? ? ? ? ? create_dir
????????????????
? ??kobject_create_and_add 函數(shù)從 構(gòu)建一個(gè)kobject到 在sysfs中創(chuàng)建路徑一氣呵成,其中沒有關(guān)于kset的設(shè)置,僅僅是設(shè)置了parent ktype
? ??如果 kobject_create_and_add 傳入的 parent 參數(shù) 是一個(gè)普通的kobject ,那么就與應(yīng)于圖中的③與⑤的關(guān)系
? ??如果 kobject_create_and_add 傳入的 parent 參數(shù) 是一個(gè)kset->kobject,那么就與應(yīng)于圖中的③與④的關(guān)系
---------------------------------------------------------------------------------------------------------------------------------------------------------------
? ??priv->kobj.kset = bus->p->drivers_kset;? // 設(shè)置它所屬的Kset
? ? ? ??? ??error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, "%s", drv->name);
?
? ??int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
???????????? struct kobject *parent, const char *fmt, ...)
? ? {
????? ??kobject_init(kobj, ktype);
? ? ? ? retval = kobject_add_varg(kobj, parent, fmt, args);
? ? }
? ? kobject_init_and_add???
????? ??kobject_init??? // kobj->ktype = ktype;
???????????? kobject_init_internal??? // kref_init(&kobj->kref);
? ? ? ? kobject_add_varg??? // retval = kobject_set_name_vargs(kobj, fmt, vargs); // kobj->parent = parent;
???????????? kobject_add_internal
?????????????? ??if (kobj->kset) {??? // 將kobject 添加到它所指向的kset->list中
?????????????????? ??if (!parent)
?????????????????????? ??parent = kobject_get(&kobj->kset->kobj);
? ? ? ? ? ? ? ? ? ? ? ? ?kobj_kset_join(kobj);
????????????????????????? kobj->parent = parent;? // 如果沒有parent 將它所屬的kset->kobj作為它的parent
??????????????????? }
????????????? create_dir
? ??與kobject_create_and_add 相比 就是少了構(gòu)建kobkject,然而這樣給了我們設(shè)置kset的機(jī)會(huì),同時(shí)往往不會(huì)設(shè)置parent
對應(yīng)于圖中的①與④的關(guān)系
---------------------------------------------------------------------------------------------------------------------------------------------------------------
? ??struct kset *kset_create_and_add(const char *name,
???????????????? struct kset_uevent_ops *uevent_ops,
???????????????? struct kobject *parent_kobj)
?????
??? ? ??kset = kset_create(name, uevent_ops, parent_kobj);
??? ? ??error = kset_register(kset);
????? }
? ??kset_create_and_add
? ? ? ??kset_create
??????????? kset = kzalloc(sizeof(*kset), GFP_KERNEL);
??????????? retval = kobject_set_name(&kset->kobj, name);
??????????? kset->uevent_ops = uevent_ops;???????
??????????? kset->kobj.parent = parent_kobj;
??????????? kset->kobj.ktype = &kset_ktype;
??????????? kset->kobj.kset = NULL;
??????? kset_register
??????????? kset_init(k);
??????????????? err = kobject_add_internal(&k->kobj);
??????????????????? parent = kobject_get(kobj->parent);
??????????????????? if (kobj->kset) {??? // kobj->kset==NULL 不執(zhí)行
?????????????????????? ....
?????????????????? }
??????????????????? error = create_dir(kobj);
??????? kset_create_and_add 無法將 創(chuàng)建kset->kobj.kset 指向任何kset
??????? 但是kset->kobj.parent 還是能和kobj.parent指向 普通的kobj 或者包含在kset里的kobj
? ??如果 kset_create_and_add 傳入的 parent 參數(shù) 是一個(gè)普通的kobject ,那么就與應(yīng)于圖中的④與⑤的關(guān)系
? ??如果 kset_create_and_add 傳入的 parent 參數(shù) 是一個(gè)kset->kobject,那么就與應(yīng)于圖中的②與④的關(guān)系
-------------------------------------------------------------------------------------------------------------------------------------------------------------
還有一種情況就是,創(chuàng)建一個(gè) kset 并設(shè)置kset.kobject.kset
然后調(diào)用 kset_register
? ? ? ? kset_register
??????????? kset_init(k);
??????????????? err = kobject_add_internal(&k->kobj);
??????????????????? parent = kobject_get(kobj->parent);
???????????????????if (kobj->kset) {??? // 將kobject 添加到它所指向的kset->list中
?????????????????? ??if (!parent)
?????????????????????? ??parent = kobject_get(&kobj->kset->kobj);
? ? ? ? ? ? ? ? ? ? ? ? ?kobj_kset_join(kobj);
????????????????????????? kobj->parent = parent;? // 如果沒有parent 將它所屬的kset->kobj作為它的parent
??????????????????? }
??????????????????? error = create_dir(kobj);
? ? 對應(yīng)于圖中④與⑥的關(guān)系。
-------------------------------------------------------------------------------------------------------------------------------------------------------------
? ??上面代碼的細(xì)節(jié),比如如何在/sys/創(chuàng)建路徑請參考:http://blog.csdn.net/lizuobin2/article/details/51511336
到此,我們應(yīng)該對 kobject kset sysfs 之間的目錄關(guān)系比較清楚了,但是我們至少還應(yīng)該看看ktype,至于Kset中的熱插拔在第二條中分析好了。
? ??struct kobject {
??? ? ??const char??????? *name;
??? ? ??struct list_head??? entry;
??? ? ??struct kobject??????? *parent;
??? ? ??struct kset??????? *kset;
??? ? ??struct kobj_type??? *ktype;
???? ?? struct kref??????? kref;
? ??……
? ??};
? ??struct kobj_type {
??? ? ??void (*release)(struct kobject *kobj);
??? ? ??struct sysfs_ops *sysfs_ops;
??? ? ??struct attribute **default_attrs;? //struct attribute *default_attrs[]
? ??};
? ??ktype 由一個(gè)release函數(shù)、一個(gè)sysfs_ops、一個(gè)指針數(shù)組(二維指針)組成
? ??1、release 函數(shù)
??? ? ??每一個(gè)Kobject 都必須有一個(gè)release方法,有意思的是,release 函數(shù)并沒有包括在kobject自身內(nèi),而是包含在它的結(jié)構(gòu)體成員Ktype內(nèi)。而且kobject在調(diào)用release之前應(yīng)該保持穩(wěn)定(不明白抄自LDD3)。
? ??2、struct attribute **default_attrs
? ? ? ??struct attribute {
? ? ? ? ? ??const char??????? *name;
? ? ? ? ? ? struct module??????? *owner;
? ? ? ? ? ? mode_t??????????? mode;
? ? ? ? };
? ? ? ? default_attrs 指向的地方 是個(gè)指針數(shù)組,這些指針的類型為attribute ,那么這些attribute 就是該kobject的屬性了,name 是屬性的名字,在kobject目錄下 表現(xiàn)為 文件 ,owner 指向模塊的指針(如果有的話),那么該模塊負(fù)責(zé)實(shí)現(xiàn)這些屬性。mode 是保護(hù)位,通常是S_IRUGO,可寫的則用S_IWUSR 僅為root提供寫權(quán)限。default_attrs最后一個(gè)元素必須為0,要不然它找不著北~
? ??3、sysfs_opes? 實(shí)現(xiàn)屬性的方法
??? ? ??struct sysfs{
??????? ? ??ssize_t *show(struct kobject *kobject, struct attribute *attr,char *buf);
??????? ? ??ssize_t *store(struct kobject *kobject, struct attribute *attr,char *buf, size_t size);
??? ? ??}
??? 在內(nèi)核里,一類設(shè)備往往使用相同的show , store函數(shù)。
附上一個(gè)例子:linux2.6.32.2 編譯通過
[cpp] view plaincopyprint?核心結(jié)論:
? ??1、sys 目錄下的層次結(jié)構(gòu)依賴于 kobject.parent ,未指定parent時(shí),默認(rèn)使用 kobject.kset.kobject 作為 parent,如果都沒有,就出現(xiàn)在 /sys 目錄下。
? ??2、該 kobject 目錄下的屬性文件依賴于 kobject.ktype
總結(jié)
以上是生活随笔為你收集整理的Linux设备驱动之Kobject、Kset的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [svc]jdk+tomcat部署.jf
- 下一篇: 随机森林模型保存-python