1.2.5.2文件類型
1.2.5.2.1磁盤文件
“文件”包含兩方面的信息:一是存儲的數(shù)據(jù)本身;還有一部分就是有關(guān)該文件的組織和管理的信息。對于磁盤文件來說,這兩種信息必定全部存儲在“文件系統(tǒng)”中,也就是磁盤上。其中與組織和管理有關(guān)的信息主要存儲在文件的“索引節(jié)點”和“目錄項”中。
在磁盤上,既是文件沒有數(shù)據(jù),其索引節(jié)點也總是存在的;目錄節(jié)電存在于所謂“目錄節(jié)點”中,目錄節(jié)點實際上是一種特殊形式和用途的文件。
1.2.5.2.2設(shè)備文件
設(shè)備文件同樣包含有用于組織和管理的信息,同樣有存儲介質(zhì)上的索引節(jié)點和目錄項,但是卻不一定有存儲著的數(shù)據(jù)。
根據(jù)設(shè)備類型和性質(zhì)的不同,它可以是用于存儲/讀出的(如磁盤),也可以是用于接收/發(fā)送的(如網(wǎng)絡(luò)卡)、還可以是供才基/控制的(如一些機電設(shè)備),甚至可以是數(shù)種類型的結(jié)合。
實際上,不管什么設(shè)備,在操作的過程中總要伴隨著一定程度的數(shù)據(jù)采集和控制,通常都通過設(shè)備接口上的一個“控制/狀態(tài)寄存器”進行。
1.2.5.2.3特殊文件
特殊文件在內(nèi)存中也由inode數(shù)據(jù)結(jié)構(gòu)和dentry數(shù)據(jù)結(jié)構(gòu),但是不一定在存儲介質(zhì)上有索引節(jié)點和目錄項。與前兩種文件主要的不同是:特殊文件一般都與外部設(shè)備無關(guān),所涉及的介質(zhì)通常就是內(nèi)存以及CPU本身。當(dāng)從一特殊文件“讀”時,所讀出的數(shù)據(jù)都是由系統(tǒng)內(nèi)部按一定的規(guī)則臨時聲稱出來的,或者從內(nèi)存中收集、加工出來的,反之亦然。
三種不同類型的文件有一個共同點,那就是他們都有一些關(guān)于組織和管理的信息。因此,每個文件都有一個inode。所謂inode,也就是“索引節(jié)點”(或稱“i節(jié)點”)的意思。給出一個索引節(jié)點號,就可以通過磁盤的設(shè)備驅(qū)動程序?qū)⑵渌诘募o(jì)錄塊賭如內(nèi)存中。(各項的詳解在書上第424頁)。
struct inode {
……
};
以linux本身的文件系統(tǒng)ext2而言,就是ext2_inode數(shù)據(jù)結(jié)構(gòu)。
struct ext2_inode {
……
};
根據(jù)一個文件的文件名就可以在磁盤上找到該文件的索引節(jié)點,從而在內(nèi)存中建立起代表該文件的inode結(jié)構(gòu),這種機制就是文件系統(tǒng)的目錄樹。這顆倒立的“樹”從系統(tǒng)的“根節(jié)點”,即“/”開始向下伸展,除最底層的“葉”節(jié)電“文件”外,其他的中間節(jié)電都是“目錄”。目錄是一種特殊的磁盤文件,它的“文件名”就是目錄名,也有索引節(jié)點,并且有數(shù)據(jù)部分。不同的是,數(shù)據(jù)部分的內(nèi)容只包括“目錄項”。對ext2文件系統(tǒng)來說,“目錄項”即ext2_dir_entry_2數(shù)據(jù)結(jié)構(gòu)。
struct ext2_dir_entry_2 {
……
};
正如磁盤上的ext2_inode數(shù)據(jù)結(jié)構(gòu)在內(nèi)存中的對應(yīng)物為inode結(jié)構(gòu)一樣,目錄項ext2_dir_entry_2在內(nèi)存中的對應(yīng)物是dentry結(jié)構(gòu),但是這二者也有很大的不同。
struct dentry {
……
};
每一個“文件系統(tǒng)”,即每一個格式化成某種文件系統(tǒng)的存儲設(shè)備上都有一個根目錄,同時又都有一個“超級塊”(super block),根目錄的位置以及文件系統(tǒng)的其他一些參數(shù)就記錄在超級塊中。超級塊在設(shè)備上的邏輯位置都是固定的,例如,在磁盤上總是在第二個邏輯塊(第一個邏輯塊位引導(dǎo)塊),所以不需要再從其他什么地方去“查找”。同時,對于一個特定的文件系統(tǒng),超級塊的格式也是固定的,系統(tǒng)在初始化時要將一個存儲設(shè)備(通常就是從引導(dǎo)出操作系統(tǒng)的那個設(shè)備)作為整個系統(tǒng)的“根設(shè)備”,它的根目錄就成為整個文件系統(tǒng)的“總根”,就是“/”。更確切地說,就是把根設(shè)備的根目錄“安裝”在文件系統(tǒng)的總根“/”結(jié)點上。有了根設(shè)備以后,還可以進而把其他存儲設(shè)備也安裝到文件系統(tǒng)中空閑的目錄節(jié)點上。所謂“安裝”,就是從一個存儲設(shè)備上讀入超級塊,在內(nèi)存中建立起一個super_block結(jié)構(gòu)。再進而將此設(shè)備上的根目錄與文件系統(tǒng)中已經(jīng)存在的一個空白目錄掛上鉤。系統(tǒng)初始化是整個文件系統(tǒng)只有一個空白目錄“/”,所以根設(shè)備的根目錄就安裝在這個節(jié)點上。這樣,從根目錄“/”開始,根據(jù)給定的“全路徑名”就可以找到文件系統(tǒng)中的任何一個文件,而不論這個文件是在哪一個存儲設(shè)備上,只要文件所在的存儲設(shè)備已經(jīng)安裝就行了。
系統(tǒng)提供了從“當(dāng)前目錄”開始查找的手段。每一個進程在每一時刻都有一個“當(dāng)前工作目錄pwd”,用戶可以改變這個目錄,但是永遠都有這么個目錄存在。
對于普通文件,文件系統(tǒng)層最終要通過磁盤或其他存儲設(shè)備的驅(qū)動程序從存儲介質(zhì)上讀或頁。就ext2文件系統(tǒng)而言,從磁盤文件的角度來看,對存儲介質(zhì)的訪問可以涉及到四種不同的目標(biāo),那就是:1)文件中的數(shù)據(jù),包括目錄的內(nèi)容,即目錄項ext2_dir_entry_2數(shù)據(jù)結(jié)構(gòu);2)文件的組織與管理信息,即索引節(jié)點ext2_inode數(shù)據(jù)結(jié)構(gòu);3)磁盤的超級塊。如果武力的磁盤被劃分成若干個分區(qū),那就包括每個“邏輯磁盤”的超級塊;4)引導(dǎo)塊。
引導(dǎo)塊 | 超級塊 | 索引節(jié)點部分,大小取決于格式化參數(shù) | 數(shù)據(jù)部分,大小取決于格式化參數(shù)和磁盤大小 |
|
實際上,具體文件系統(tǒng)與虛擬文件系統(tǒng)VFS間的界面是一組數(shù)據(jù)結(jié)構(gòu),包括:
1)文件操作跳轉(zhuǎn)標(biāo),即file_operation數(shù)據(jù)結(jié)構(gòu):file結(jié)構(gòu)中的指針f_op指向具體的file_operations結(jié)構(gòu),這是read()、write()等文件操作的跳轉(zhuǎn)表。一種文件系統(tǒng)并不只限于一個file_operations結(jié)構(gòu),如ext2就有兩個這樣的數(shù)據(jù)結(jié)構(gòu),分別用于普通文件和目錄文件。
2)目錄項操作跳轉(zhuǎn)表,即dentry_operations數(shù)據(jù)結(jié)構(gòu):dentry結(jié)構(gòu)中的指針d_op指向具體的dentry_operations數(shù)據(jù)結(jié)構(gòu),這是內(nèi)何種hash()、compare()等內(nèi)部操作得跳轉(zhuǎn)表。如果d_op為0則表示按linux默認(rèn)的(即ext2)方式辦。注意,這里說的目錄項,而不是目錄,目錄本身是一種特殊用途和具有特殊結(jié)構(gòu)的文件。
3)索引節(jié)點操作跳轉(zhuǎn)表,即inode_operations數(shù)據(jù)結(jié)構(gòu):inode結(jié)構(gòu)中的指針i_op指向具體的inode_operations數(shù)據(jù)結(jié)構(gòu),這是mkdir()、mknod()等文件操作以及lockup()_、permission()等內(nèi)部函數(shù)的跳轉(zhuǎn)表。同樣,一種文件系統(tǒng)也并不只限于一個fle_operations結(jié)構(gòu)。
4)超級塊操作跳轉(zhuǎn)表,即super_operations數(shù)據(jù)結(jié)構(gòu):<span lang="EN-US" style="FONT-S
2. 從路徑名到目標(biāo)節(jié)點
Dentry簡要地總結(jié)(代碼在1.2.5.3.1)
--每個dentry結(jié)構(gòu)都通過隊列頭d_hash鏈入雜湊表dentry_hashtable中的某個隊列里。
--共享計數(shù)為0的dentry結(jié)構(gòu)都通過隊列頭d_lru鏈入LRU隊列dentry_unused,在隊列中等待釋放或者“東山再起”。
--每個dentry結(jié)構(gòu)都通過指針d_inode指向一個inode數(shù)據(jù)結(jié)構(gòu)。但是多個dentry結(jié)構(gòu)可以指向同一個inode數(shù)據(jù)結(jié)構(gòu)。
--指向同一個inode數(shù)據(jù)結(jié)構(gòu)的dentry結(jié)構(gòu)都通過隊列頭d_alias連接在一起,都在該inode結(jié)構(gòu)的i_dentry隊列中。
--每個dentry結(jié)構(gòu)都通過指針d_sb指向一個super_block數(shù)據(jù)結(jié)構(gòu)。
--每個dentry結(jié)構(gòu)都通過指針d_op指向一個dentry_operation數(shù)據(jù)結(jié)構(gòu)。
--每個dentry結(jié)構(gòu)都有個隊列頭d_vfsmnt,用于文件系統(tǒng)的安裝。
以_usr_walk為例,走一下它的流程。