Linux那些事兒之我是Sysfs_第1頁(yè)
Linux那些事兒之我是Sysfs_第2頁(yè)
Linux那些事兒之我是Sysfs_第3頁(yè)
Linux那些事兒之我是Sysfs_第4頁(yè)
Linux那些事兒之我是Sysfs_第5頁(yè)
已閱讀5頁(yè),還剩64頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Linux那些事兒之我是Sysfs來(lái)源于: HYPERLINK /fudan_abc /fudan_abc HYPERLINK /fudan_abc/archive/2007/09/01/1768277.aspx Linux那些事兒之我是Sysfs(1)sysfs初探sysfs is a ram-based filesystem initially based on ramfs. It provides a meansto export kernel data structures, their attributes, and the linkages between them tousers

2、pace.” documentation/filesystems/sysfs.txt可 以先把documentation/filesystems/sysfs.txt讀一遍。文檔這種東西,真正讀起來(lái)就嫌少了。Sysfs文件系統(tǒng)是一個(gè)類(lèi) 似于proc文件系統(tǒng)的特殊文件系統(tǒng),用于將系統(tǒng)中的設(shè)備組織成層次結(jié)構(gòu),并向用戶(hù)模式程序提供詳細(xì)的內(nèi)核數(shù)據(jù)結(jié)構(gòu)信息。去/sys看一看,localhost:/sys#ls /sys/block/ bus/ class/ devices/ firmware/ kernel/ module/ power/Block目錄:包含所有的塊設(shè)備Devices目錄:包含系統(tǒng)所有的設(shè)

3、備,并根據(jù)設(shè)備掛接的總線(xiàn)類(lèi)型組織成層次結(jié)構(gòu)Bus目錄:包含系統(tǒng)中所有的總線(xiàn)類(lèi)型Drivers目錄:包括內(nèi)核中所有已注冊(cè)的設(shè)備驅(qū)動(dòng)程序Class目錄:系統(tǒng)中的設(shè)備類(lèi)型(如網(wǎng)卡設(shè)備,聲卡設(shè)備等)sys下面的目錄和文件反映了整臺(tái)機(jī)器的系統(tǒng)狀況。比如bus,localhost:/sys/bus#lsi2c/ ide/ pci/ pci express/ platform/ pnp/ scsi/ serio/ usb/里面就包含了系統(tǒng)用到的一系列總線(xiàn),比如pci, ide, scsi, usb等等。比如你可以在usb文件夾中發(fā)現(xiàn)你使用的U盤(pán),USB鼠標(biāo)的信息。我們要討論一個(gè)文件系統(tǒng),首先要知道這個(gè)文件系

4、統(tǒng)的信息來(lái)源在哪里。所謂信息來(lái)源是指文件組織存放的地點(diǎn)。比如,我們掛載一個(gè)分區(qū),mount -t vfat /dev/hda2 /mnt/C我們就知道掛載在/mnt/C下的是一個(gè)vfat類(lèi)型的文件系統(tǒng),它的信息來(lái)源是在第一塊硬盤(pán)的第2個(gè)分區(qū)。但是,你可能根本沒(méi)有去關(guān)心過(guò)sysfs的掛載過(guò)程,她是這樣被掛載的。mount -t sysfs sysfs /sysms看不出她的信息來(lái)源在哪。sysfs是一個(gè)特殊文件系統(tǒng),并沒(méi)有一個(gè)實(shí)際存放文件的介質(zhì)。斷電后就玩完了。簡(jiǎn)而言之,sysfs的信息來(lái)源是kobject層次結(jié)構(gòu),讀一個(gè)sysfs文件,就是動(dòng)態(tài)的從kobject結(jié)構(gòu)提取信息,生成文件。所以,首

5、先,我要先講一講sysfs文件系統(tǒng)的信息來(lái)源 - kobject層次結(jié)構(gòu)。kobject層次結(jié)構(gòu)就是linux的設(shè)備模型。莫愁前路無(wú)知己,天下誰(shuí)人不識(shí)君。 唐高適 別董大 HYPERLINK /fudan_abc/archive/2007/09/01/1768296.aspx Linux那些事兒之我是Sysfs(2)linux設(shè)備底層模型關(guān)于linux設(shè)備模型網(wǎng)上有一些論述,有些東西我就用了拿來(lái)主義,進(jìn)行了修改和整理。1 KobjectKobject 是Linux 2.6引入的新的設(shè)備管理機(jī)制,在內(nèi)核中由struct kobject表示。通過(guò)這個(gè)數(shù)據(jù)結(jié)構(gòu)使所有設(shè)備在底層都具有統(tǒng)一的接口,kob

6、ject提供基本的對(duì)象管理,是構(gòu)成Linux2.6設(shè)備模型的核心結(jié) 構(gòu),它與sysfs文件系統(tǒng)緊密關(guān)聯(lián),每個(gè)在內(nèi)核中注冊(cè)的kobject對(duì)象都對(duì)應(yīng)于sysfs文件系統(tǒng)中的一個(gè)目錄。Kobject是組成設(shè)備模型的基 本結(jié)構(gòu)。類(lèi)似于C+中的基類(lèi),它嵌入于更大的對(duì)象的對(duì)象中-所謂的容器-用來(lái)描述設(shè)備模型的組件。如bus,devices, drivers 都是典型的容器。這些容器就是通過(guò)kobject連接起來(lái)了,形成了一個(gè)樹(shù)狀結(jié)構(gòu)。這個(gè)樹(shù)狀結(jié)構(gòu)就與/sys向?qū)?yīng)。kobject 結(jié)構(gòu)為一些大的數(shù)據(jù)結(jié)構(gòu)和子系統(tǒng)提供了基本的對(duì)象管理,避免了類(lèi)似機(jī)能的重復(fù)實(shí)現(xiàn)。這些機(jī)能包括- 對(duì)象引用計(jì)數(shù).- 維護(hù)對(duì)象鏈表

7、(集合).- 對(duì)象上鎖.- 在用戶(hù)空間的表示.Kobject結(jié)構(gòu)定義為:struct kobject char * k name; 指向設(shè)備名稱(chēng)的指針char nameKOBJ NAME LEN; 設(shè)備名稱(chēng)struct kref kref; 對(duì)象引用計(jì)數(shù)struct list head entry; 掛接到所在kset中去的單元struct kobject * parent; 指向父對(duì)象的指針struct kset * kset; 所屬kset的指針struct kobj type * ktype; 指向其對(duì)象類(lèi)型描述符的指針struct dentry * dentry; sysfs文件系統(tǒng)中

8、與該對(duì)象對(duì)應(yīng)的文件節(jié)點(diǎn)路徑指針;其 中的kref域表示該對(duì)象引用的計(jì)數(shù),內(nèi)核通過(guò)kref實(shí)現(xiàn)對(duì)象引用計(jì)數(shù)管理,內(nèi)核提供兩個(gè)函數(shù)kobject_get()、kobject_put() 分別用于增加和減少引用計(jì)數(shù),當(dāng)引用計(jì)數(shù)為0時(shí),所有該對(duì)象使用的資源釋放。Ktype 域是一個(gè)指向kobj type結(jié)構(gòu)的指針,表示該對(duì)象的類(lèi)型。相關(guān)函數(shù)void kobject_init(struct kobject * kobj);kobject初始化函數(shù)。int kobject_set_name(struct kobject *kobj, const char *format, .);設(shè)置指定kobject的名

9、稱(chēng)。struct kobject *kobject_get(struct kobject *kobj);將kobj 對(duì)象的引用計(jì)數(shù)加1,同時(shí)返回該對(duì)象的指針。void kobject_put(struct kobject * kobj); 將kobj對(duì)象的引用計(jì)數(shù)減1,如果引用計(jì)數(shù)降為0,則調(diào)用kobject release()釋放該kobject對(duì)象。int kobject_add(struct kobject * kobj);將kobj對(duì)象加入Linux設(shè)備層次。掛接該kobject對(duì)象到kset的list鏈中,增加父目錄各級(jí)kobject的引用計(jì)數(shù),在其 parent指向的目錄下創(chuàng)建文件

10、節(jié)點(diǎn),并啟動(dòng)該類(lèi)型內(nèi)核對(duì)象的hotplug函數(shù)。int kobject_register(struct kobject * kobj);kobject注冊(cè)函數(shù)。通過(guò)調(diào)用kobject init()初始化kobj,再調(diào)用kobject_add()完成該內(nèi)核對(duì)象的注冊(cè)。void kobject_del(struct kobject * kobj);從Linux設(shè)備層次(hierarchy)中刪除kobj對(duì)象。void kobject_unregister(struct kobject * kobj);kobject注銷(xiāo)函數(shù)。與kobject register()相反,它首先調(diào)用kobject de

11、l從設(shè)備層次中刪除該對(duì)象,再調(diào)用kobject put()減少該對(duì)象的引用計(jì)數(shù),如果引用計(jì)數(shù)降為0,則釋放kobject對(duì)象。2 Kobj typestruct kobj_type void (*release)(struct kobject *);struct sysfs_ops * sysfs_ops;struct attribute * default_attrs;Kobj type數(shù)據(jù)結(jié)構(gòu)包含三個(gè)域:一個(gè)release方法用于釋放kobject占用的資源;一個(gè)sysfs ops指針指向sysfs操作表和一個(gè)sysfs文件系統(tǒng)缺省屬性列表。Sysfs操作表包括兩個(gè)函數(shù)store()和sh

12、ow()。當(dāng)用戶(hù)態(tài)讀取屬性 時(shí),show()函數(shù)被調(diào)用,該函數(shù)編碼指定屬性值存入buffer中返回給用戶(hù)態(tài);而store()函數(shù)用于存儲(chǔ)用戶(hù)態(tài)傳入的屬性值。attributestruct attribute char * name;struct module * owner;mode_t mode;attribute, 屬性。它以文件的形式輸出到sysfs的目錄當(dāng)中。在kobject對(duì)應(yīng)的目錄下面。文件名就是name。文件讀寫(xiě)的方法對(duì)應(yīng)于kobj type中的sysfs ops。3. ksetkset 最重要的是建立上層(sub-system)和下層的(kobject)的關(guān)聯(lián)性。kobject

13、 也會(huì)利用它了分辨自已是屬于那一個(gè)類(lèi)型,然後在/sys 下建立正確的目錄位置。而kset 的優(yōu)先權(quán)比較高,kobject會(huì)利用自已的*kset 找到自已所屬的kset,並把*ktype 指定成該kset下的ktype,除非沒(méi)有定義kset,才會(huì)用ktype來(lái)建立關(guān)系。Kobject通過(guò)kset組織成層次化的結(jié)構(gòu),kset是具有相 同類(lèi)型的kobject的集合,在內(nèi)核中用kset數(shù)據(jù)結(jié)構(gòu)表示,定義為:struct kset struct subsystem * subsys; 所在的subsystem的指針struct kobj type * ktype; 指向該kset對(duì)象類(lèi)型描述符的指針st

14、ruct list head list; 用于連接該kset中所有kobject的鏈表頭struct kobject kobj; 嵌入的kobjectstruct kset hotplug ops * hotplug ops; 指向熱插拔操作表的指針;包 含在kset中的所有kobject被組織成一個(gè)雙向循環(huán)鏈表,list域正是該鏈表的頭。Ktype域指向一個(gè)kobj type結(jié)構(gòu),被該kset中的所有kobject共享,表示這些對(duì)象的類(lèi)型。Kset數(shù)據(jù)結(jié)構(gòu)還內(nèi)嵌了一個(gè)kobject對(duì)象(由kobj域表示),所 有屬于這個(gè)kset 的kobject對(duì)象的parent域均指向這個(gè)內(nèi)嵌的對(duì)象。此外

15、,kset還依賴(lài)于kobj維護(hù)引用計(jì)數(shù):kset的引用計(jì)數(shù)實(shí)際上就是內(nèi)嵌的 kobject對(duì)象的引用計(jì)數(shù)。見(jiàn)圖1,kset與kobject的關(guān)系圖這幅圖很經(jīng)典,她反映了整個(gè)kobject的連接情況。相關(guān)函數(shù)與kobject 相似,kset_init()完成指定kset的初始化,kset_get()和kset_put()分別增加和減少kset對(duì)象的引用計(jì)數(shù)。 Kset_add()和kset_del()函數(shù)分別實(shí)現(xiàn)將指定keset對(duì)象加入設(shè)備層次和從其中刪除;kset_register()函數(shù)完成 kset的注冊(cè)而kset_unregister()函數(shù)則完成kset的注銷(xiāo)。4 subsystem如

16、 果說(shuō)kset 是管理kobject 的集合,同理,subsystem 就是管理kset 的集合。它描述系統(tǒng)中某一類(lèi)設(shè)備子系統(tǒng),如block subsys表示所有的塊設(shè)備,對(duì)應(yīng)于sysfs文件系統(tǒng)中的block目錄。類(lèi)似的,devices subsys對(duì)應(yīng)于sysfs中的devices目錄,描述系統(tǒng)中所有的設(shè)備。Subsystem由struct subsystem數(shù)據(jù)結(jié)構(gòu)描述,定義為:struct subsystem struct kset kset; 內(nèi)嵌的kset對(duì)象struct rw semaphore rwsem; 互斥訪(fǎng)問(wèn)信號(hào)量;可以看出,subsystem與kset的區(qū)別就是多了一

17、個(gè)信號(hào)量,所以在后來(lái)的代碼中,subsystem已經(jīng)完全被kset取締了。每個(gè)kset屬于某個(gè)subsystem,通過(guò)設(shè)置kset結(jié)構(gòu)中的subsys域指向指定的subsystem可以將一個(gè)kset加入到該subsystem。所有掛接到同一subsystem的kset共享同一個(gè)rwsem信號(hào)量,用于同步訪(fǎng)問(wèn)kset中的鏈表。相關(guān)函數(shù)subsystem有一組類(lèi)似的函數(shù),分別是:void subsystem_init(struct subsystem *subsys);int subsystem_register(struct subsystem *subsys);void subsystem_u

18、nregister(struct subsystem *subsys);struct subsystem *subsys_get(struct subsystem *subsys)void subsys_put(struct subsystem *subsys);關(guān)于那些函數(shù)的用法,會(huì)在后面的舉例中詳細(xì)講。這里僅僅是一個(gè)介紹。 HYPERLINK /fudan_abc/archive/2007/09/01/1768315.aspx Linux那些事兒之我是Sysfs(3)設(shè)備模型上層容器1 bus系統(tǒng)中總線(xiàn)由struct bus_type描述,定義為:struct bus_type char

19、* name; 總線(xiàn)類(lèi)型的名稱(chēng)struct subsystem subsys; 與該總線(xiàn)相關(guān)的subsystemstruct kset drivers; 所有與該總線(xiàn)相關(guān)的驅(qū)動(dòng)程序集合struct kset devices; 所有掛接在該總線(xiàn)上的設(shè)備集合struct bus attribute * bus_attrs; 總線(xiàn)屬性struct device attribute * dev_attrs; 設(shè)備屬性struct driver attribute * drv_attrs; 驅(qū)動(dòng)程序?qū)傩詉nt (*match)(struct device * dev, struct device_dri

20、ver * drv);int (*hotplug) (struct device *dev, char *envp, int num_envp, char *buffer, int buffer_size);int (*suspend)(struct device * dev, u32 state);int (*resume)(struct device * dev);;每 個(gè)bus_type對(duì)象都內(nèi)嵌一個(gè)subsystem對(duì)象,bus_subsys對(duì)象管理系統(tǒng)中所有總線(xiàn)類(lèi)型的subsystem對(duì)象。每個(gè) bus_type對(duì)象都對(duì)應(yīng)/sys/bus目錄下的一個(gè)子目錄,如PCI總線(xiàn)類(lèi)型對(duì)應(yīng)于/s

21、ys/bus/pci。在每個(gè)這樣的目錄下都存在兩個(gè)子目 錄:devices和drivers(分別對(duì)應(yīng)于bus type結(jié)構(gòu)中的devices和drivers域)。其中devices子目錄描述連接在該總線(xiàn)上的所有設(shè)備,而drivers目錄則描述與該總線(xiàn)關(guān)聯(lián) 的所有驅(qū)動(dòng)程序。與device_driver對(duì)象類(lèi)似,bus_type結(jié)構(gòu)還包含幾個(gè)函數(shù)(match()、hotplug()等)處理相應(yīng)的熱插 拔、即插即拔和電源管理事件。2 device系統(tǒng)中的任一設(shè)備在設(shè)備模型中都由一個(gè)device對(duì)象描述,其對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)struct device定義為:struct device struct lis

22、t_head g_list;struct list_head node;struct list_head bus_list;struct list_head driver_list;struct list_head children;struct device *parent;struct kobject kobj;char bus_idBUS_ID_SIZE;struct bus_type *bus;struct device_driver *driver;void *driver_data;/* Several fields omitted */;g_list 將該device對(duì)象掛接到全

23、局設(shè)備鏈表中,所有的device對(duì)象都包含在devices subsys中,并組織成層次結(jié)構(gòu)。Node域?qū)⒃搶?duì)象掛接到其兄弟對(duì)象的鏈表中,而bus list則用于將連接到相同總線(xiàn)上的設(shè)備組織成鏈表,driver list則將同一驅(qū)動(dòng)程序管理的所有設(shè)備組織為鏈表。此外,children域指向該device對(duì)象子對(duì)象鏈表頭,parent域則指向父對(duì)象。 Device對(duì)象還內(nèi)嵌一個(gè)kobject對(duì)象,用于引用計(jì)數(shù)管理并通過(guò)它實(shí)現(xiàn)設(shè)備層次結(jié)構(gòu)。Driver域指向管理該設(shè)備的驅(qū)動(dòng)程序?qū)ο?,?driver data則是提供給驅(qū)動(dòng)程序的數(shù)據(jù)。Bus域描述設(shè)備所連接的總線(xiàn)類(lèi)型。內(nèi)核提供了相應(yīng)的函數(shù)用于操作

24、device對(duì)象。其中device_register()函數(shù)將一個(gè)新的device對(duì)象插入設(shè)備模型,并自動(dòng)在/sys/devices下創(chuàng)建一個(gè)對(duì) 應(yīng)的目錄。device_unregister()完成相反的操作,注銷(xiāo)設(shè)備對(duì)象。get_device()和put_device()分別增加與減少設(shè) 備對(duì)象的引用計(jì)數(shù)。通常device結(jié)構(gòu)不單獨(dú)使用,而是包含在更大的結(jié)構(gòu)中作為一個(gè)子結(jié)構(gòu)使用,比如描述PCI設(shè)備的struct pci_dev,還有我們ldd_dev,其中的dev域就是一個(gè)device對(duì)象。3. driver系統(tǒng)中的每個(gè)驅(qū)動(dòng)程序由一個(gè)device_driver對(duì)象描述,對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)定義為:

25、struct device_driver char *name; 設(shè)備驅(qū)動(dòng)程序的名稱(chēng)struct bus_type *bus; 該驅(qū)動(dòng)所管理的設(shè)備掛接的總線(xiàn)類(lèi)型struct kobject kobj; 內(nèi)嵌kobject對(duì)象struct list_head devices; 該驅(qū)動(dòng)所管理的設(shè)備鏈表頭int (*probe)(struct device *dev); 指向設(shè)備探測(cè)函數(shù),用于探測(cè)設(shè)備是否可以被該驅(qū)動(dòng)程序管理int (*remove)(struct device *dev); 用于刪除設(shè)備的函數(shù)/* some fields omitted*/;與device 結(jié)構(gòu)類(lèi)似,device_

26、driver對(duì)象依靠?jī)?nèi)嵌的kobject對(duì)象實(shí)現(xiàn)引用計(jì)數(shù)管理和層次結(jié)構(gòu)組織。內(nèi)核提供類(lèi)似的函數(shù)用于操作 device_driver對(duì)象,如get_driver()增加引用計(jì)數(shù),driver_register()用于向設(shè)備模型插入新的driver對(duì) 象,同時(shí)在sysfs文件系統(tǒng)中創(chuàng)建對(duì)應(yīng)的目錄。device_driver()結(jié)構(gòu)還包括幾個(gè)函數(shù),用于處理熱拔插、即插即用和電源管理事件??赡苣忝鎸?duì)剛剛列舉出來(lái)的一些列數(shù)據(jù)結(jié)構(gòu),感到很苦惱,很莫名其妙。沒(méi)關(guān)系,我接下來(lái)講個(gè)例子您就明白了。 HYPERLINK /fudan_abc/archive/2007/09/01/1768384.aspx Linu

27、x那些事兒之我是Sysfs(4)舉例一lddbus對(duì)了,你得把ldd3的examples代碼下下來(lái)。不然沒(méi)法繼續(xù)了。接下來(lái)我們從例子著手,localhost:/home/XX/examples/lddbus#insmod lddbus.ko此時(shí)再看/sys/bus/ 這時(shí)就多了一個(gè)文件夾ldd。里面的文件構(gòu)成是這樣的/sys/bus/ldd/|-device|-driver-versionlocalhost:/sys/bus/ldd#cat version$Revision: 1.9$這表示系統(tǒng)中多了一種名叫l(wèi)dd的總線(xiàn)類(lèi)型。同時(shí)再看/sys/device/,也多出來(lái)一個(gè)ldd0的文件夾。這表

28、示系統(tǒng)中多了一個(gè)名叫l(wèi)dd0的硬件。在lddbus.c中, 定義了一個(gè)總線(xiàn)和硬件類(lèi)型struct bus_type ldd_bus_type = .name = ldd, .match = ldd_match, .hotplug = ldd_hotplug,;struct device ldd_bus = .bus_id = ldd0, .release = ldd_bus_release;lddbus模塊初始化時(shí)調(diào)用這個(gè)函數(shù)static int _init ldd_bus_init(void) int ret; ret = bus_register(&ldd_bus_type); if (r

29、et) return ret; if (bus_create_file(&ldd_bus_type, &bus_attr_version) printk(KERN_NOTICE Unable to create version attributen); ret = device_register(&ldd_bus); if (ret) printk(KERN_NOTICE Unable to register ldd0n); return ret;其實(shí)就是調(diào)用了兩個(gè)注冊(cè)函數(shù),bus_register(), device_register()。bus_create_file()是在sysfs下創(chuàng)

30、建一個(gè)文件夾。bus_register(),向系統(tǒng)注冊(cè)ldd_bus_type這個(gè)總線(xiàn)類(lèi)型。bus_create_file()這個(gè)就是向sysfs中創(chuàng)建一個(gè)文件。device_register()系統(tǒng)注冊(cè)ldd_bus這個(gè)硬件類(lèi)型。注冊(cè)好了之后,我們就可以在sysfs下看到相應(yīng)的信息。我們深入下去,仔細(xì)看看bus_register的代碼。 688 int bus_register(struct bus_type * bus) 689 690 int retval; 691 692 retval = kobject_set_name(&bus-subsys.kset.kobj, %s, bus-

31、name); 693 if (retval) 694 goto out; 695 696 subsys_set_kset(bus, bus_subsys); 697 retval = subsystem_register(&bus-subsys); 698 if (retval) 699 goto out; 700 701 kobject_set_name(&bus-devices.kobj, devices); 702 bus-devices.subsys = &bus-subsys; 703 retval = kset_register(&bus-devices); 704 if (ret

32、val) 705 goto bus_devices_fail; 706 707 kobject_set_name(&bus-drivers.kobj, drivers); 708 bus-drivers.subsys = &bus-subsys; 709 bus-drivers.ktype = &ktype_driver; 710 retval = kset_register(&bus-drivers); 711 if (retval) 712 goto bus_drivers_fail; 713 bus_add_attrs(bus); 714 715 pr_debug(bus type %s

33、 registeredn, bus-name); 716 return 0; 717 718 bus_drivers_fail: 719 kset_unregister(&bus-devices); 720 bus_devices_fail: 721 subsystem_unregister(&bus-subsys); 722 out: 723 return retval; 724 692-700是對(duì)bus-subsys的操作。701-705是操作bus-devices。706-710是操作bus-drivers。692kobject_set_name()設(shè)置bus-subsys.kset.k

34、obj的名字。此函數(shù)很簡(jiǎn)單,就是調(diào)用vsnprintf()。此不列出。696 subsys_set_kset(bus, bus subsys)#define subsys_set_kset(obj,_subsys)(obj)-subsys.kset.kobj.kset = &(_subsys).kset我 們先看看bus_subsys的定義,它是一個(gè)subsystem類(lèi)型的全局變量。在driver/base/bus.c中,decl subsys(bus, &ktype bus, NULL); 在/include/linux/kobject.h中有,decl subsys的原型,#define

35、decl_subsys(_name,_type,_hotplug_ops) struct subsystem _name#_subsys = .kset = .kobj = .name = _stringify(_name) , .ktype = _type, .hotplug_ops =_hotplug_ops, 就相當(dāng)于struct subsystem bus_subsys = .kset = .kobj = .name = “bus” , .ktype = ktype_bus, .hotplug_ops =NULL, 其中ktype bus定義如下,static struct kobj_

36、type ktype_bus = .sysfs_ops = &bus_sysfs_ops,;697subsystem_register(&bus-subsys)作用是向全局的bus_subsys”登記”, 把自己加入到bus_subsys的鏈表中去。subsystem_register() - kset_add() - kobject_add() 155 int kobject_add(struct kobject * kobj) 156 157 int error = 0; 158 struct kobject * parent; 159 160 if (!(kobj = kobject_g

37、et(kobj) 161 return -ENOENT; 162 if (!kobj-k_name) 163 kobj-k_name = kobj-name; 164 parent = kobject_get(kobj-parent); 165 166 pr_debug(kobject %s: registering. parent: %s, set: %sn, 167 kobject_name(kobj), parent ? kobject_name(parent) : , 168 kobj-kset ? kobj-kset- : ); 169 170 if (kobj-kset) 171

38、down_write(&kobj-kset-subsys-rwsem); 172 173 if (!parent) 174 parent = kobject_get(&kobj-kset-kobj); 175 176 list_add_tail(&kobj-entry,&kobj-kset-list); 177 up_write(&kobj-kset-subsys-rwsem); 178 179 kobj-parent = parent; 180 181 error = create_dir(kobj); 182 if (error) 183 /* unlink does the kobjec

39、t_put() for us */ 184 unlink(kobj); 185 if (parent) 186 kobject_put(parent); 187 else 188 kobject_hotplug(kobj, KOBJ_ADD); 189 190 191 return error; 192 代碼的170-178就是把自己連入到父輩上級(jí)kset中。我們注意到在kobject_add()函數(shù)中181行調(diào)用了create_dir(kobj),這個(gè)函數(shù)作用是在sysfs下創(chuàng)建一個(gè)文件夾??梢?jiàn)kobject和sysfs是同時(shí)更新的。kset_register(&bus-devices) 和

40、kset_register(&bus-drivers)作用類(lèi)似,把bus-devices這個(gè)kset加入到bus- subsys這個(gè)subsystem中去。最后形成圖1的層次結(jié)構(gòu)。圖1:lddbus kobject層次結(jié)構(gòu)同理,我們可以看看device_register()的代碼,它也是向devices_subsys這個(gè)subsystem注冊(cè),最后形成這樣的結(jié)構(gòu)與圖1類(lèi)似。目前為止,我們知道了所謂的xx_register函數(shù),就是通過(guò)其內(nèi)嵌的kobject鏈入對(duì)應(yīng)的subsystem,或是kset的層次結(jié)構(gòu)中去。這樣就可以通過(guò)一些全局的變量找到它們了。 HYPERLINK /fudan_abc

41、/archive/2007/09/01/1768417.aspx Linux那些事兒之我是Sysfs(5)舉例二sculld不妨再把sculld的代碼也分析一下,先看初始函數(shù)sculld_init() - register_ldd_driver()-driver_register()-bus_add_driver() - register_ldd_device() -device_register() -device_add() -kobject_add() -bus_add_device()首先注冊(cè)驅(qū)動(dòng),看bus_add_driver() 532 int bus_add_driver(str

42、uct device_driver * drv) 533 534 struct bus_type * bus = get_bus(drv-bus); 535 int error = 0; 536 537 if (bus) 538 pr_debug(bus %s: add driver %sn, bus-name, drv-name); 539 error = kobject_set_name(&drv-kobj, %s, drv-name); 540 if (error) 541 put_bus(bus); 542 return error; 543 544 drv-kobj.kset = &

43、bus-drivers; 545 if (error = kobject_register(&drv-kobj) 546 put_bus(bus); 547 return error; 548 549 550 down_write(&bus-subsys.rwsem); 551 driver_attach(drv); 552 up_write(&bus-subsys.rwsem); 553 module_add_driver(drv-owner, drv); 554 555 driver_add_attrs(bus, drv); 556 557 return error; 558 559 54

44、5行kobject_register()與kobject_add()差不多,進(jìn)行注冊(cè),把自己kobject鏈接到內(nèi)核中去。551,driver_attach(drv); 在總線(xiàn)中尋找,有沒(méi)有設(shè)備可以讓這個(gè)driver驅(qū)動(dòng)。 353 void driver_attach(struct device_driver * drv) 354 355 struct bus_type * bus = drv-bus; 356 struct list_head * entry; 357 int error; 358 359 if (!bus-match) 360 return; 361 362 list_fo

45、r_each(entry, &bus-devices.list) 363 struct device * dev = container_of(entry, struct device, bus_list); 364 if (!dev-driver) 365 error = driver_probe_device(drv, dev); 366 if (error & (error != -ENODEV) 367 /* driver matched but the probe failed */ 368 printk(KERN_WARNING 369 %s: probe of %s failed

46、 with error %dn, 370 drv-name, dev-bus_id, error); 371 372 373 然后注冊(cè)設(shè)備, 455 int bus_add_device(struct device * dev) 456 457 struct bus_type * bus = get_bus(dev-bus); 458 int error = 0; 459 460 if (bus) 461 down_write(&dev-bus-subsys.rwsem); 462 pr_debug(bus %s: add device %sn, bus-name, dev-bus_id);

47、463 list_add_tail(&dev-bus_list, &dev-bus-devices.list); 464 465 up_write(&dev-bus-subsys.rwsem); 466 device_add_attrs(bus, dev); 467 sysfs_create_link(&bus-devices.kobj, &dev-kobj, dev-bus_id); 468 469 return error; 470 463,把設(shè)備連入其總線(xiàn)的devices.list鏈表中。464,device_attach(dev)與driver_attach()相對(duì)應(yīng),它在總線(xiàn)的驅(qū)動(dòng)中

48、尋找,看有沒(méi)有一個(gè)driver能驅(qū)動(dòng)這個(gè)設(shè)備。467,創(chuàng)建了一個(gè)鏈接。最后形成的kobject層次結(jié)構(gòu)如圖所示。變化計(jì)劃趕不上變化,當(dāng)前的內(nèi)核版本已經(jīng)是2.6.22了,其中不少數(shù)據(jù)結(jié)構(gòu)作了變動(dòng),而且subsystem這個(gè)數(shù)據(jù)結(jié)構(gòu)已經(jīng)沒(méi)有了,完全被kset取締了。但是原理上并沒(méi)有變,我認(rèn)為,學(xué)習(xí)知識(shí)是一方面,更重要的是學(xué)習(xí)方法。只要懂了方法,我們才可以不變應(yīng)萬(wàn)變。17大馬上要召開(kāi)了,劉翔又奪冠了,奧爾默特與阿巴斯也會(huì)面了,明年就奧運(yùn)了。和諧的社會(huì)里充滿(mǎn)著希望與絕望。不管怎樣,終于把設(shè)備模型介紹完畢,接下來(lái)進(jìn)入sysfs部分。人面不知何處去,桃花依舊笑春風(fēng)。 唐崔護(hù)題都城南莊 HYPERLINK

49、/fudan_abc/archive/2007/09/03/1770965.aspx Linux那些事兒之我是Sysfs(6)文件系統(tǒng)接下來(lái),我們進(jìn)入sysfs部分??纯磌object_add()-create_dir()-sysfs_create_dir()bus create file-sysfs create file(). . .這些sysfs函數(shù)的內(nèi)幕。說(shuō)白了,sysfs就是利用VFS的接口去讀寫(xiě)kobject的層次結(jié)構(gòu),建立起來(lái)的文件系統(tǒng)。關(guān)于sysfs的內(nèi)容就在fs/sysfs/下。kobject的層次結(jié)構(gòu)的更新與刪除就是那些亂七八糟的XX_register()們干的事情。在ko

50、bject_add()里面,調(diào)用了sysfs_create_dir()。讓我們看看它究竟是如何create的。 135 int sysfs_create_dir(struct kobject * kobj) 136 137 struct dentry * dentry = NULL; 138 struct dentry * parent; 139 int error = 0; 140 141 BUG_ON(!kobj); 142 143 if (kobj-parent) 144 parent = kobj-parent-dentry; 145 else if (sysfs_mount & sy

51、sfs_mount-mnt_sb) 146 parent = sysfs_mount-mnt_sb-s_root; 147 else 148 return -EFAULT; 149 150 error = create_dir(kobj,parent,kobject_name(kobj),&dentry); 151 if (!error) 152 kobj-dentry = dentry; 153 return error; 154 當(dāng) 你看見(jiàn)這么些新東西,如dentry出現(xiàn)的時(shí)候,你一定感到很困惑。誠(chéng)然,我一度為代碼中突然出現(xiàn)的事物感到恐慌,人類(lèi)對(duì)未知的恐懼是與生俱來(lái)的,面對(duì)死 亡,面對(duì)怪力

52、亂神,我們抱著一顆敬畏的心靈就可以了。而面對(duì)linux,我們始終堅(jiān)信,未知肯定是可以被探索出來(lái)的。妖是妖他媽生的,代碼是人他媽寫(xiě)出來(lái) 的,既然寫(xiě)得出來(lái),那就肯定看得懂。對(duì)不起,扯遠(yuǎn)了我還是介紹介紹文件系統(tǒng)的基本知識(shí)先。文件系統(tǒng)文 件系統(tǒng)是個(gè)很模糊廣泛的概念,文件狹義地說(shuō),是指磁盤(pán)文件,廣義理解,可以是有組織有次序地存儲(chǔ)與任何介質(zhì)(包括內(nèi)存)的一組信息。linux把所有 的資源都看成是文件,讓用戶(hù)通過(guò)一個(gè)統(tǒng)一的文件系統(tǒng)操作界面,也就是同一組系統(tǒng)調(diào)用,對(duì)屬于不同文件系統(tǒng)的文件進(jìn)行操作。這樣,就可以對(duì)用戶(hù)程序隱藏各種 不同文件系統(tǒng)的實(shí)現(xiàn)細(xì)節(jié),為用戶(hù)程序提供了一個(gè)統(tǒng)一的,抽象的,虛擬的文件系統(tǒng)界面,這

53、就是所謂VFS(Virtual Filesystem Switch)。這個(gè)抽象出來(lái)的接口就是一組函數(shù)操作。我們要實(shí)現(xiàn)一種文件系統(tǒng)就是要實(shí)現(xiàn)VFS所定義的一系列接口, file_operations, dentry_operations, inode_operations等,供上層調(diào)用。file_operations是對(duì)每個(gè)具體文件的讀寫(xiě)操作,dentry_operations, inode_operations則是對(duì)文件的屬性,如改名字,建立或刪除的操作。struct file_operations ssize_t (*read) (struct file *, char _user *, s

54、ize_t, loff_t *);ssize_t (*write) (struct file *, const char _user *, size_t, loff_t *);int (*open) (struct inode *, struct file *);.;struct dentry_operations .;struct inode_operations int (*create) (struct inode *,struct dentry *,int, struct nameidata *);struct dentry * (*lookup) (struct inode *,st

55、ruct dentry *, struct nameidata *);int (*link) (struct dentry *,struct inode *,struct dentry *);int (*mkdir) (struct inode *,struct dentry *,int);int (*rmdir) (struct inode *,struct dentry *);.舉個(gè)例子,我們寫(xiě)C程序,open(“hello.c”, O_RDONLY),它通過(guò)系統(tǒng)調(diào)用的流程是這樣的open() - /*用戶(hù)空間*/- 系統(tǒng)調(diào)用-sys_open() - filp_open()- dentr

56、y_open() -file_operations-open() /*內(nèi)核空間*/不同的文件系統(tǒng),調(diào)用不同的file_operations-open(),在sysfs下就是sysfs_open_file()。 HYPERLINK /fudan_abc/archive/2007/09/06/1775313.aspx Linux那些事兒之我是Sysfs(7)dentry與inode我們?cè)谶M(jìn)程中要怎樣去描述一個(gè)文件呢?我們用目錄項(xiàng)(dentry)和索引節(jié)點(diǎn)(inode)。它們的定義如下:struct dentry struct inode *d_inode; /* Where the name be

57、longs to - NULL isstruct dentry *d_parent; /* parent directory */struct list_head d_child; /* child of parent list */struct dentry_operations*d_op;struct super_block*d_sb; /* The root of the dentry tree */void *d_fsdata; /* fs-specific data */unsigned char d_inameDNAME_INLINE_LEN_MIN; /* small names

58、 */;struct inode unsigned longi_ino;atomic_ti_count;umode_t i_mode;unsigned inti_nlink;uid_t i_uid;gid_t i_gid;dev_t i_rdev;loff_t i_size;struct timespeci_atime;unsigned longi_blocks;unsigned shorti_bytes;unsigned char _sock;12struct inode_operations *i_op;struct file_operations *i_fop; /* former -i

59、_op-default_file_ops */struct super_block *i_sb; 所謂文件, 就是按一定的形式存儲(chǔ)在介質(zhì)上的信息,所以一個(gè)文件其實(shí)包含了兩方面的信息,一是存儲(chǔ)的數(shù)據(jù)本身,二是有關(guān)該文件的組織和管理的信息。在內(nèi)存中, 每個(gè)文件都有一個(gè)dentry(目錄項(xiàng))和inode(索引節(jié)點(diǎn))結(jié)構(gòu),dentry記錄著文件名,上級(jí)目錄等信息,正是它形成了我們所看到的樹(shù)狀結(jié)構(gòu); 而有關(guān)該文件的組織和管理的信息主要存放inode里面,它記錄著文件在存儲(chǔ)介質(zhì)上的位置與分布。同時(shí)dentry-d_inode指向相應(yīng)的 inode結(jié)構(gòu)。dentry與inode是多對(duì)一的關(guān)系,因?yàn)橛锌赡芤粋€(gè)

60、文件有好幾個(gè)文件名(硬鏈接, hard link, 可以參考這個(gè)網(wǎng)頁(yè) HYPERLINK http:/www.ugrad.cs.ubc.ca/%7Ecs219/CourseNotes/Unix/commands-links.html http:/www.ugrad.cs.ubc.ca/cs219/CourseNotes/Unix/commands-links.html)。所有的dentry用d_parent和d_child連接起來(lái),就形成了我們熟悉的樹(shù)狀結(jié)構(gòu)。inode 代表的是物理意義上的文件,通過(guò)inode可以得到一個(gè)數(shù)組,這個(gè)數(shù)組記錄了文件內(nèi)容的位置,如該文件位于硬盤(pán)的第3,8,10塊,

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論