聊聊磁盤(pán)文件系統(tǒng)(一)
1 磁盤(pán)是怎樣工作的?
第一類(lèi),機(jī)械磁盤(pán),也稱(chēng)為硬盤(pán)驅(qū)動(dòng)器(Hard Disk Driver),通??s寫(xiě)為 HDD。磁盤(pán)有多個(gè)盤(pán)片,每個(gè)盤(pán)片雙面存儲(chǔ)。磁道(Track)磁頭(Head)在盤(pán)片上畫(huà)出的不同半徑的同心圓。柱面(Cylinder)全部盤(pán)片相同磁道組成的圓柱側(cè)面。柱面是從0開(kāi)始編號(hào),由外向內(nèi)。柱面越靠外,吞吐量越大。(因?yàn)樵娇客廪D(zhuǎn)動(dòng)的線(xiàn)速度越大。扇區(qū)(Sector)盤(pán)片上的扇形區(qū)域。每個(gè)扇區(qū)512字節(jié)。是硬盤(pán)的基本單位。從1開(kāi)始編號(hào)。每個(gè)扇區(qū)中的數(shù)據(jù)作為一個(gè)單元同時(shí)讀出或?qū)懭?。硬盤(pán)的0柱面0磁頭1扇區(qū)是系統(tǒng)啟動(dòng)時(shí)首先讀取的扇區(qū)。
第二類(lèi),固態(tài)磁盤(pán)(Solid State Disk),通??s寫(xiě)為 SSD,由固態(tài)電子元器件組成。固態(tài)磁盤(pán)不需要磁道尋址,所以,不管是連續(xù) I/O,還是隨機(jī) I/O 的性能,都比機(jī)械磁盤(pán)要好得多。
2 磁盤(pán)邏輯結(jié)構(gòu)概觀(guān)
磁盤(pán)讀寫(xiě)的最小單位是扇區(qū),然而扇區(qū)只有 512B 大小,如果每次都讀寫(xiě)這么小的單位,效率一定很低。所以,文件系統(tǒng)Ext又把連續(xù)的扇區(qū)組成了邏輯塊,然后每次都以邏輯塊為最小單元,來(lái)管理數(shù)據(jù)。常見(jiàn)的邏輯塊大小為 4KB,也就是由連續(xù)的 8 個(gè)扇區(qū)組成。a)如果是一個(gè)啟動(dòng)盤(pán),我們需要預(yù)留一塊區(qū)域作為引導(dǎo)區(qū),所以第一個(gè)塊組的前面要留 1K,用于啟動(dòng)引導(dǎo)區(qū)。b)磁盤(pán)在執(zhí)行文件系統(tǒng)格式化時(shí),會(huì)被分成三個(gè)存儲(chǔ)區(qū)域,超級(jí)塊、索引節(jié)點(diǎn)區(qū)和數(shù)據(jù)塊區(qū)。
- 索引節(jié)點(diǎn):簡(jiǎn)稱(chēng)為 inode,用來(lái)記錄文件的元數(shù)據(jù),比如 inode 編號(hào)、文件大小、訪(fǎng)問(wèn)權(quán)限、修改日期、數(shù)據(jù)的位置等。索引節(jié)點(diǎn)和文件一一對(duì)應(yīng),它跟文件內(nèi)容一樣,都會(huì)被持久化存儲(chǔ)到磁盤(pán)中。所以記住,索引節(jié)點(diǎn)同樣占用磁盤(pán)空間。
- 數(shù)據(jù)塊:簡(jiǎn)稱(chēng)為block,普通文件用來(lái)記錄文件的數(shù)據(jù)。目錄文件的塊里面保存的是目錄里面一項(xiàng)一項(xiàng)的文件信息,每一項(xiàng)都會(huì)保存這個(gè)目錄的下一級(jí)的文件的文件名和對(duì)應(yīng)的 inode,通過(guò)這個(gè) inode,就能找到真正的文件。第一項(xiàng)是“.”,表示當(dāng)前目錄,第二項(xiàng)是“…”,表示上一級(jí)目錄,接下來(lái)就是一項(xiàng)一項(xiàng)的文件名和 inode。
- 超級(jí)塊:簡(jiǎn)稱(chēng)為super_block。用于存儲(chǔ)文件系統(tǒng)自身元數(shù)據(jù)的核心結(jié)構(gòu)。其中的信息包括空閑和以使用塊的數(shù)目、塊長(zhǎng)度、當(dāng)前文件系統(tǒng)的狀態(tài)、各種時(shí)間戳。還包括一個(gè)表示文件系統(tǒng)類(lèi)型的魔數(shù),能檢查mount確認(rèn)文件系統(tǒng)的類(lèi)型是否正確。一般只使用塊組0中的超級(jí)塊,因此也叫主超級(jí)塊。如果主超級(jí)塊信息損壞,可以從超級(jí)塊的備份信息中復(fù)制數(shù)據(jù)來(lái)修復(fù)。c)另外還有幾個(gè)概念了解一下:
- 組描述符表(GDT):組描述符表包含的信息反映了文件系統(tǒng)中各個(gè)塊組的狀態(tài)。其中信息包含塊組中空閑塊和空閑inode的數(shù)目。每個(gè)塊組都包含了文件系統(tǒng)中所有塊組的組描述符信息。由于GDT對(duì)于定位文件系統(tǒng)的元數(shù)據(jù)非常重要,因此和超級(jí)塊一樣,也對(duì)其進(jìn)行了備份。GDT及其備份的內(nèi)容都是一樣的,所占?jí)K數(shù)也相同。
- inode位圖:用二進(jìn)制的方式記錄了inode的使用情況, 比如inode是否空閑等。
- 數(shù)據(jù)塊位圖:用二進(jìn)制方式記錄了塊的使用情況。當(dāng)查找或創(chuàng)建文件時(shí),會(huì)掃描此位圖來(lái)尋找空閑的inode號(hào)對(duì)應(yīng)的塊。一個(gè)塊組可以有32768(40968)個(gè)邏輯塊。每一個(gè)塊組均有自己的塊位圖與inode位圖,用于記錄本塊組中塊與inode的使用情況。一個(gè)邏輯塊的大小為4K。則一個(gè)塊位圖所描述的塊組最大為40968*4K=128MB。
- inode列表:包含了塊組中所有的inode,inode用于保存文件系統(tǒng)中與各個(gè)文件和目錄相連的所有元數(shù)據(jù)。
重要數(shù)據(jù)備份
默認(rèn)情況下,超級(jí)塊和塊組描述符表都有副本保存在每一個(gè)塊組里面。如果開(kāi)啟了 sparse_super(稀疏超級(jí)快) 特性,超級(jí)塊和塊組描述符表的副本只會(huì)保存在塊組索引為 0、3、5、7 的整數(shù)冪里。除了塊組 0 中存在一個(gè)超級(jí)塊外,在塊組 1(30=1)的第一個(gè)塊中存在一個(gè)副本;在塊組 3(31=3)、塊組 5(51=5)、塊組 7(71=7)、塊組 9(32=9)、塊組 25(52=25)、塊組 27(33=27)的第一個(gè) block 處也存在一個(gè)副本。對(duì)于超級(jí)塊來(lái)講,由于超級(jí)塊不是很大,所以就算我們備份多了也沒(méi)有太多問(wèn)題。但是,對(duì)于塊組描述符表來(lái)講,如果每個(gè)塊組里面都保存一份完整的塊組描述符表,一方面很浪費(fèi)空間;另一個(gè)方面,由于一個(gè)塊組最大 128M,而塊組描述符表里面有多少項(xiàng),這就限制了有多少個(gè)塊組,128M * 塊組的總數(shù)目是整個(gè)文件系統(tǒng)的大小,就被限制住了。這樣會(huì)產(chǎn)生一個(gè)限制,以Ext4的塊組描述符大小64 Bytes計(jì)算,文件系統(tǒng)中最多只能有2^21個(gè)塊組,也就是文件系統(tǒng)最大為256TB。
Flexible Block Groups
這是ext4引入的一個(gè)特點(diǎn)。就是將連續(xù)的多個(gè)block groups綁在一起組成一個(gè)邏輯塊組,稱(chēng)之為flex_group。在一個(gè)flex_group中,第一個(gè)物理block group是存放當(dāng)前flex_group全部的bitmap、inode表。也就是說(shuō)將幾個(gè)塊組合并為一個(gè)更大的塊組。比如flex_group的大小為4(就是由4個(gè)塊組組成),其中的group0將按順序存放Super Block、GDT、4個(gè)塊組的塊位圖、4個(gè)塊組的inode位圖、4個(gè)塊組的inode表,剩余的空間是用作數(shù)據(jù)塊。就是說(shuō)ext4將幾個(gè)塊組合并為一個(gè)更大的塊組。
flex_group塊組的作用是:
- 聚集元數(shù)據(jù),加速元數(shù)據(jù)載入
- 使得大文件在磁盤(pán)上盡量連續(xù) 即使開(kāi)啟flex_bg特性,超級(jí)塊和塊組描述符的冗余備份仍然位于塊組的開(kāi)頭。Flex_bg中塊組的個(gè)數(shù)由2^ext4_super_block.s_log_groups_per_flex 給出。這是為了減少磁盤(pán)尋道操作,將頻繁訪(fǎng)問(wèn)的塊組資源放在連續(xù)空間上。同時(shí)也能一次申請(qǐng)更多的塊;因?yàn)橐淮涡陨暾?qǐng)的塊最大數(shù)目是一個(gè)組的塊數(shù)。
Ext4引入Meta Block Groups
首先,塊組描述符表不會(huì)保存所有塊組的描述符了,而是將塊組分成多個(gè)組,我們稱(chēng)為元塊組(Meta Block Group)。每個(gè)元塊組里面的塊組描述符表僅僅包括自己的,一個(gè)元塊組包含 64 個(gè)塊組,這樣一個(gè)元塊組中的塊組描述符表最多 64 項(xiàng)。我們假設(shè)一共有 256 個(gè)塊組,原來(lái)是一個(gè)整的塊組描述符表,里面有 256 項(xiàng),要備份就全備份,現(xiàn)在分成 4 個(gè)元塊組,每個(gè)元塊組里面的塊組描述符表就只有 64 項(xiàng)了,這就小多了,而且四個(gè)元塊組自己備份自己的。
根據(jù)圖中,每一個(gè)元塊組包含 64 個(gè)塊組,塊組描述符表也是 64 項(xiàng),備份三份,在元塊組的第一個(gè),第二個(gè)和最后一個(gè)塊組的開(kāi)始處。這樣化整為零,我們就可以發(fā)揮出 ext4 的 48 位塊尋址的優(yōu)勢(shì)了,在超級(jí)塊 ext4_super_block 的定義中,我們可以看到塊尋址分為高位和低位,均為 32 位,其中有用的是 48 位,2^48 個(gè)塊是 1EB,足夠用了。
- struct ext4_super_block {
- ......
- __le32 s_blocks_count_lo; /* Blocks count */
- __le32 s_r_blocks_count_lo; /* Reserved blocks count */
- __le32 s_free_blocks_count_lo; /* Free blocks count */
- ......
- __le32 s_blocks_count_hi; /* Blocks count */
- __le32 s_r_blocks_count_hi; /* Reserved blocks count */
- __le32 s_free_blocks_count_hi; /* Free blocks count */
- ......
- }
3 數(shù)據(jù)塊和Inode分配策略
在機(jī)械磁盤(pán)上,保持相關(guān)的數(shù)據(jù)塊相互接近可以總的磁頭移動(dòng)時(shí)間,因而可以加速磁盤(pán)IO。在SSD上雖然沒(méi)有磁頭轉(zhuǎn)動(dòng),數(shù)據(jù)局部性可以增加每次IO請(qǐng)求的傳輸?shù)臄?shù)據(jù)大小,因而減少響應(yīng)IO請(qǐng)求的傳輸次數(shù)。數(shù)據(jù)的局部性對(duì)單個(gè)擦除塊的寫(xiě)入產(chǎn)生影響,可以加速文件重寫(xiě)的速度。因而盡可能減少碎片是必要的。inode和數(shù)據(jù)塊的分配策略可以保證數(shù)據(jù)的局部集中。以下為inode和數(shù)據(jù)塊的分配策略:
- 多塊分配可以減少磁盤(pán)碎片。當(dāng)文件初次創(chuàng)建的時(shí)候,塊分配器預(yù)測(cè)性地分配8KB的磁盤(pán)空間給文件。當(dāng)文件關(guān)閉的時(shí)候,未使用的空間當(dāng)然也就釋放了。但是如果推測(cè)是正確的,那么文件數(shù)據(jù)將寫(xiě)到一個(gè)多個(gè)塊的extent中。
- 延遲分配。當(dāng)一個(gè)文件需要更多的數(shù)據(jù)塊引起寫(xiě)操作時(shí),文件系統(tǒng)推遲決定新數(shù)據(jù)在磁盤(pán)上的存放位置,直到臟的buffer寫(xiě)到磁盤(pán)為止。
- 盡量保持文件的數(shù)據(jù)塊與其inode在同一個(gè)塊組中。可以減少磁盤(pán)尋道時(shí)間.
- 盡量保持同一個(gè)目錄中的所有inodes與目錄位于同一個(gè)塊組中。這樣的假設(shè)前提是一個(gè)目錄中的文件是相關(guān)的。
- 磁盤(pán)卷被分成128MB的塊組。當(dāng)在根目錄中創(chuàng)建目錄時(shí),inode分配器掃描塊組并將新目錄放到它找到的使用負(fù)荷最小的塊組中。這可以保證目錄在磁盤(pán)上的分散性。
- 即使上述機(jī)制無(wú)效,仍然可以使用e4defrag整理碎片文件。
4 硬鏈接與軟鏈接
a)硬鏈接:
- 多個(gè)文件指向同一個(gè)inode,這些文件的inode number相同
- 硬鏈接表明文件可以通過(guò)不同的文件名訪(fǎng)問(wèn)
- 不能對(duì)目錄創(chuàng)建硬鏈接
- 硬鏈接不能跨分區(qū)
- 每多一個(gè)硬鏈接,inode的引用計(jì)數(shù)(鏈接數(shù))+1 b)軟鏈接(符號(hào)鏈接):
- 文件及其軟鏈接文件,使用的不是同一個(gè)inode,inode number不一樣;
- 軟鏈接文件的實(shí)際數(shù)據(jù)是另一個(gè)文件的路徑,是一個(gè)字符串,軟鏈接文件的大小為該字符串的長(zhǎng)度;
- 可以對(duì)目錄創(chuàng)建軟鏈接
- 軟鏈接可以跨分區(qū)
- 增加文件軟鏈接,不會(huì)增加inode的引用計(jì)數(shù)