最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

全知乎獨(dú)一無二的Linux設(shè)備模型(二)(超詳細(xì))

2022-04-02 14:36 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿
  • 上一篇文章《全知乎獨(dú)一無二的Linux設(shè)備模型(一)(超詳細(xì))》主要介紹了Linux設(shè)備模型在用戶空間的接口sysfs,用戶通過這個(gè)接口可以一覽內(nèi)核設(shè)備的全貌。本文將從Linux內(nèi)核的角度來看一看這個(gè)設(shè)備模型是如何構(gòu)建的。

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

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



  • 在接下來的篇幅里我們會(huì)逐步看到這個(gè)關(guān)系圖在內(nèi)核里是如何建立的。本文的示例代碼可以從這里下載,下文中的兩個(gè)實(shí)作都在這個(gè)示例代碼里。

  • Kobject

  • Kobject在Linux內(nèi)核里的定義如下:

《全知乎獨(dú)一無二的Linux設(shè)備模型(一)(超詳細(xì))》里面我們介紹到內(nèi)核里的設(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用來指向kobject的父對(duì)象;Kref大家應(yīng)該比較熟悉了,kobject通過它來實(shí)現(xiàn)引用計(jì)數(shù);Kset指針用來指向這個(gè)kobject所屬的kset,下文會(huì)再詳細(xì)描述kset的用法;對(duì)于ktype,如果只是望文生義的話,應(yīng)該是用來描述kobject的類型信息。Ktype的定義如下:

  • 函數(shù)指針release是給kref使用的,當(dāng)引用計(jì)數(shù)為0這個(gè)指針指向的函數(shù)會(huì)被調(diào)用來釋放內(nèi)存。sysfs_ops和attribute是做什么用的呢?前文里提到,一個(gè)kobject對(duì)應(yīng)sysfs里的一個(gè)目錄,而目錄下的文件就是由sysfs_ops和attribute來實(shí)現(xiàn)的,其中,attribute定義了kobject的屬性,在sysfs里對(duì)應(yīng)一個(gè)文件,sysfs_ops用來定義讀寫這個(gè)文件的方法。Ktype里的attribute是默認(rèn)的屬性,另外也可以使用更加靈活的手段,本文的重點(diǎn)還是放在default attribute。

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。?!前100名進(jìn)群領(lǐng)取,額外贈(zèng)送一份價(jià)值699的內(nèi)核資料包(含視頻教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)?

?

  • 下面看一個(gè)實(shí)作。在這個(gè)實(shí)作里,我們定義一個(gè)內(nèi)嵌kobject的結(jié)構(gòu)。

  • 最終我們的目的是在內(nèi)核里構(gòu)建這樣的架構(gòu)。


  • 對(duì)應(yīng)sysfs里的目錄關(guān)系是:

mykobj1/?

|-- mykobj2?

| |-- name?

| `-- val?

|-- name `-- val

  • 這是module_init代碼。

  • 這段代碼可以分作三個(gè)部分。第一部分是分配obj1和obj2并賦值;第二部分是初始化kobj_type變量my_type;第三部分是調(diào)用kobject_init_and_add函數(shù)來初始化kobject并把它加入到設(shè)備模型的體系架構(gòu)(也就是上文中提到的內(nèi)核中的那棵樹)中。kobject_init_and_add是簡(jiǎn)化的寫法,這個(gè)函數(shù)也可以分兩步完成:kobject_init和kobject_add。

  • kobject_init用來初始化kobject結(jié)構(gòu),kobject_add用來把kobj加入到設(shè)備模型之中。在實(shí)作中,我們先對(duì)obj1進(jìn)行初始化和添加的動(dòng)作,調(diào)用參數(shù)里,parent被賦為NULL,表示obj1沒有父對(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,但也提供了另外的接口供用戶使用。

  • kobject_init_and_add和kobject_init這兩個(gè)函數(shù)被調(diào)用后,kobj的引用計(jì)數(shù)會(huì)初始化為1,所以在module_exit時(shí)要記得用kobject_put來釋放引用計(jì)數(shù)。


  • 我們?cè)倩氐綄?shí)作中,看看如何使用ktype。代碼里,my_attrs是這樣定義的:

  • 結(jié)構(gòu)體struct attribute里的name變量用來指定文件名,mode變量用來指定文件的訪問權(quán)限。這里需要著重指出的是,數(shù)組my_attrs的最后一項(xiàng)一定要賦為NULL,否則會(huì)造成內(nèi)核oops。


  • sysfs_ops的代碼如下:

  • 讀文件會(huì)調(diào)用my_show,寫文件會(huì)調(diào)用my_store。


  • 最后是module_exit:

  • kobject_del的作用是把kobject從設(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來增加父對(duì)象的引用計(jì)數(shù),所以kobject_del需要調(diào)用kobject_put來減少父對(duì)象的引用計(jì)數(shù)。在本例中,如果先通過kobject_put來釋放obj1,那kobject_del(&obj2->kobj)就會(huì)出現(xiàn)內(nèi)存錯(cuò)誤。


  • 在這個(gè)實(shí)作中,我們建立了兩個(gè)對(duì)象obj1和obj2,obj1是obj2的父對(duì)象,如果推廣開來,obj1可以有更多的子對(duì)象。在Linux內(nèi)核中,這種架構(gòu)方式其實(shí)并無太大的實(shí)際價(jià)值,有限的用處之一是在sysfs里創(chuàng)建子目錄(Linux內(nèi)核里有這種用法,這種情況下,直接調(diào)用內(nèi)核提供的kobject_create來實(shí)現(xiàn),不需要自定義數(shù)據(jù)結(jié)構(gòu)并內(nèi)嵌kobject),而且,創(chuàng)建子目錄也是有其他的辦法的。我們知道,Linux設(shè)備模型最初的目的是為了方便電源管理,這就需要從上到下的遍歷,在這種架構(gòu)里,通過obj1并無法訪問其所有的子對(duì)象。這個(gè)實(shí)作最大的意義在于可以讓我們比較清晰的理解kobject如何使用。通常情況下,kobject只需要在葉節(jié)點(diǎn)里使用,上層的節(jié)點(diǎn)要使用kset。

  • Kset

  • Kset的定義如下:

  • Kset結(jié)構(gòu)里的kobj表明它也是一個(gè)kobject,list變量用來組織它所有的子對(duì)象。


  • 我們直接看一個(gè)實(shí)作。在這個(gè)實(shí)作里,我們將構(gòu)建如下的架構(gòu)。

  • 對(duì)應(yīng)sysfs里的目錄關(guān)系是:

  • my_kset/

  • |-- mykobj1

  • | ? |-- name

  • | ? `-- val `-- mykobj2 ? ?

  • |-- name ? ?`-- val

  • 這個(gè)實(shí)作和前一個(gè)差別很小,下面只簡(jiǎn)略的引用一些代碼。

  • 在module_init里,我們首先調(diào)用kset_create_and_add創(chuàng)建my_kset,接下來把my_kset賦給obj1和obj2,最后調(diào)用kobject_init_and_add來添加obj1和obj2。這里需要注意的是,kobject_init_and_add參數(shù)里的parent都是NULL,在這種情況下,obj1和obj2的父對(duì)象由kobject結(jié)構(gòu)里的kset指針決定,在這個(gè)實(shí)作里就是my_kset。在module_exit里,我們還需要額外調(diào)用kset_unregister來釋放之前創(chuàng)建的my_kset。


  • 注:看過LDD3的讀者應(yīng)該對(duì)Linux Device Model一章中的subsystem還有印象,我在這里注明一下,從2.6.23開始Linux內(nèi)核就拋棄了subsystem,subsystem其實(shí)只是kset的一個(gè)馬甲,所以拋棄它對(duì)Linux設(shè)備模型并沒什么影響。



全知乎獨(dú)一無二的Linux設(shè)備模型(二)(超詳細(xì))的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
辰溪县| 铁岭县| 浙江省| 元谋县| 扎囊县| 广元市| 漠河县| 加查县| 延长县| 灵璧县| 龙里县| 鸡泽县| 佳木斯市| 临潭县| 延津县| 东乡族自治县| 中牟县| 定日县| 辽中县| 邢台市| 景德镇市| 雅安市| 周至县| 临邑县| 高阳县| 云浮市| 琼中| 乌拉特前旗| 咸丰县| 克拉玛依市| 定襄县| 万荣县| 噶尔县| 枣强县| 洪江市| 思南县| 耒阳市| 怀安县| 永昌县| 柳江县| 静宁县|