對檔案系統而言,檔案僅是一系列可讀寫的資料塊。檔案系統并不需要了解資料塊應該放到實體媒體上什麼位置。這些都是裝置驅動的任務。無論何時,隻要檔案系統需要從包含它的塊裝置中讀取資訊或資料,它就将請求底層的裝置驅動讀取一個基本塊大小整數倍的資料塊。EXT2檔案系統将它所使用的邏輯分區劃分成資料塊組。每個資料塊組都将那些對檔案系統完整性最重要的資訊複制出來,同時将實際檔案盒目錄看做資訊與資料塊。
羅即檔案系統管理的是一個邏輯空間,這個邏輯空間就像一個大的數組,數組的每個元素就是檔案系統操作的基本機關——邏輯塊。邏輯塊是從0開始編号的,而且,邏輯塊是連續的,邏輯塊相對的是實體塊。通常,EXT2的實體塊占一個或幾個連續的扇區。
一般而言,隻有塊組0的超級塊才讀入記憶體,其他塊組的超級塊僅僅作為備份。在系統運作期間,要将超級塊複制到記憶體系統緩沖區。
在EXT2檔案系統中,采用位圖描述資料塊和索引節點的使用情況,每個塊組中占用兩個塊,即一個用來描述該資料塊的使用情況,另一個描述該組索引節點的使用情況。這兩個塊分别稱為資料位圖塊和索引節點位圖塊。資料位圖塊中的每一位表示該塊組中的每一個塊的使用情況,如果為0,則表示相應資料塊空閑,如果是1,則表示已配置設定。
每個塊組中的索引節點都存儲在各自的索引節點表中,并且按索引節點号依次存儲。索引節點表通常占好幾個資料塊,索引節點表所占的塊使用時也想普通的資料塊一樣被調入塊高速緩存。
EXT2整個磁盤的邏輯結構如圖所示:
超級塊中包含了描述檔案系統基本尺寸和形态的資訊。檔案系統管理器利用他們來使用和維護檔案系統。EXT2超級塊是用來描述EXT2檔案系統整體資訊的資料結構,是EXT2的核心所在。超級塊經函數ext2_fill_supter讀入後,又在記憶體中建立一個映像super_block.u.ext2_sb_info結構。
結構ext2_super_block列出如下:
邏輯塊是從0開始編号的,對塊大小為1KB的檔案系統,s_first_data_block為1,對其他檔案系統,則為0.
EXT2超級塊被讀入記憶體後,主要用于填寫VFS的超級塊。此外,它還要填寫另外一個結構ext2_super_info。結構ext2_super_info描述了EXT2檔案系統特定的資訊。之是以要用到這個結構,是因為VFS的超級塊必須相容各種檔案系統的不同的超級塊結構,是以每個檔案系統超級塊特定的特性必須用另一個結構儲存于記憶體中,以加快對檔案的操作。EXT2超級塊與VFS超級塊的關系如圖所示:
結構ext2_super_info列出如下:
超級塊的操作函數結構如下所示:
在EXT2檔案系統中每個檔案與目錄由惟一的inode來描述。每個資料塊組的EXT2 inode被儲存在inode表中,同時還有一個位圖被系統用來跟蹤已配置設定和未配置設定的inode。
EXT2檔案系統使用索引節點來記錄檔案資訊。每個普通檔案盒目錄都有惟一的索引節點與之對應,索引節點中含有檔案或目錄的重要資訊。當你要通路一個檔案或目錄時,通過檔案或目錄名首先找到與之對應的索引節點,然後通過索引節點得到檔案或目錄的資訊及磁盤上的具體的存儲位置。
EXT2在硬碟上的索引節點的資料結構如下:
EXT2通過索引節點中的資料塊指針數組進行邏輯塊到實體塊的映射。在EXT2索引節點中,資料塊中數組共有15項,前12個為直接指針,後三個分别為“一次間接指針”、“二次間接指針”、“三次間接指針”,EXT2預設的實體塊大小為1KB,塊位址占4個位元組,是以每個實體塊可以存儲256個位址。這樣,檔案大小最大可達12KB+256KB+64MB+16GB。但實際上,Linux是32位系統,故檔案大小最大隻能為4GB,及整個檔案系統都被一個檔案所占用。索引節點的實體塊指針數組如圖所示:
系統是以邏輯塊号為索引查找實體塊的。例如,要找到第100個邏輯塊對應的實體塊,因為256+12>100>12,是以要用到一次間接塊,在一次間接塊中查找第88項,此項内容就是對應的實體塊的位址。
節點在磁盤上是經過編号的。其中,有一些節點有特殊用途,使用者不能使用。這些特殊節點定義為:
與EXT2超級塊類似,當磁盤上的索引節點調入記憶體後,除了要填寫VFS的索引節點外,系統還要根據它填寫另一個資料結構ext2_inode_info,其作用也是為了存儲特定檔案系統自己的特性。
結構ext2_inode_info分析如下:
VFS索引節點中沒有實體塊指針數組的域,這個EXT2特有的資訊在調入記憶體後,就必須保持在ext2_inode_info這個結構中。
在塊組中緊跟着超級塊後面的塊是組描述符,在start_sect+block_size*2位置上。乘以2的原因是block_size是KByte為機關,我們用扇區通路。組描述符表每一項為組描述符,是一個叫ext2_group_desc的資料結構,供32位元組。它用來描述某個塊組的整體資訊。
找到了組描述符,可得到很多資訊,如該組塊組位圖的位置,該組塊inode位圖位置,該組塊inode表的位置等。
組描述符的定義如下:
在 函數init_ext2_fs注冊了EXT2檔案系統,函數分析如下:
檔案系統執行個體ext2_fs_type列出如下:
函數ext2_get_sb打開塊裝置,得到超級塊,将這個超級塊加到全局super_blocks連結清單中,并挂接檔案系統。函數ext2_get_sb列出如下:
函數ext2_fill_super從硬碟中讀出超級塊資料并填充超級塊結構。
超級塊操作函數集執行個體ext2_sops列出如下:
檔案的讀寫操作都調用到具體檔案系統的讀寫操作函數結構,這裡即調用到EXT2檔案系統的ext2_file_operations結構,得到具體的操作函數。
下圖為read系統調用的操作函數層次圖,可見EXT2檔案系統的讀操作最終調用ext2_readpage函數完成,對于檔案讀操作過程中的檔案對記憶體的映射過程。
結構ext2_file_operations是EXT2檔案系統對于檔案的操作函數集,列出如下:
ext2_aops結構是EXT2 檔案系統中具體操作實作函數集,它被ext2_file_operations結構的函數所調用。列出如下:
ext2_aops結構中的這些函數列出如下:
這些函數除了調用的ext2_get_block函數是EXT2檔案系統特有的外,其他都是fs/buffer.c中的函數。
ext2_get_block()将對檔案系統的邏輯塊号轉換為塊裝置的邏輯塊号。這種轉化關系是由ext2_inode結構中i_block[]數組描述的i_block[]的前12項為直接索引表,第13項為間接索引塊指針,第14項為二重索引塊指針,第15項為三重索引塊指針。當檔案長度不超過12個塊時,可通過直接塊索引表直接定位目标塊;當檔案長度超過12塊,并且剩餘的部分不超過間接塊索引數量時,就在間接塊索引塊中定位目标塊,依次類推。
函數ext2_get_block功能是從邏輯塊序号得到對應實體塊。若對應實體塊被删除,則重新配置設定,并得到它間接塊路徑。
函數ext2_get_block具體分析如下:
函數ext2_get_branch從實體塊中讀取資料到chain的buffer中,函數的參數說明如下:
inode 操作的節點
depth 間接塊的深度
offset 間接實體塊的指針數組
chain 存儲讀取實體塊的資料
存儲錯誤标志
函數ext2_get_branch的功能是填充Indirect結構的數組,如果運作正常,則傳回NULL。函數分析如下:
函數ext2_alloc_branch配置設定并建立一個塊連結清單,其中參數inode表示需配置設定塊的節點,參數num表示間接塊的深度,參數offsets是一個數組,即offsets[num],參數branch是存儲連結清單的地方。函數分析如下:
檔案系統普遍存在的一個問題是碎片化,即一個檔案所包含的資料塊遍布整個檔案系統,這使得對檔案資料塊的順序通路越來越慢。EXT2檔案系統試圖通過配置設定一個和目前檔案資料塊在實體位置上鄰接,或者至少位于同一個資料塊組中的新塊來解決這個問題。
在EXT2中,目錄是一種特殊的檔案,它是由ext2_dir_entry結構組成的清單。為了減少磁盤空間的浪費,這個結構是可變長的。但是,它還有一定的長度方面的限制:一是檔案名最長隻能為255個字元;二是盡管檔案名長度可以不限,但系統自動将之變成4的整數倍,不足的地方用0填充。
EXT2把檔案名和檔案資訊分開存儲,其中檔案資訊用索引節點來描述,目錄項是用來聯系檔案名和索引節點的。目錄項中,每一對檔案名和索引節點号的一個一一對應稱為一個連結,這就是說,同一個索引節點表可以對應多個不同的檔案名。這種連結稱為硬連結。可以用ln指令為一個已存在的檔案建立一個新的硬連結:
ln /home/cyf/file1 /home/cyf/file2
建立了一個檔案file2,連結到file1上。file2和file1有相同的索引節點号,也就是和file1共享同一個索引節點。在建立了一個新的硬連結後,這個索引節點中的i_links_count值将加1,i_links_count的值反映了連結到這個索引節點上的檔案數。
使用硬連結的好處在于:
1)由于删除檔案時,實際上先對i_links_count做減1,如果i_links_count不為0,則結束,即僅僅删除了一個硬連結,實際檔案的資料并沒有删除。隻有在i_links_count為0時,真正将檔案從磁盤上删除。這樣,你可以對重要的檔案作多個連結,防止檔案被删除。
2)允許使用者在不進入某個目錄的情況下對該目錄下面的檔案進行處理。
符号連結與硬連結最大的不同就在于它并不與索引節點建立連結,也就是說,當為一個檔案建立一個符号連結時,索引節點的連結計數并不變化。當你删除一個檔案時,它的符号連結檔案也就失去了作用,而當你删除一個檔案的符号連結檔案,對該檔案本身并無影響。