一,Linux文件系統(tǒng)
1,文件系統(tǒng)是什么
- 文件系統(tǒng)是操作系統(tǒng)用于明確存儲(chǔ)設(shè)備(常見(jiàn)的有磁盤(pán),固態(tài)硬盤(pán)等)或分區(qū)上的文件的方法和數(shù)據(jù)結(jié)構(gòu),即在存儲(chǔ)設(shè)備上組織文件的方法。
- 操作系統(tǒng)中負(fù)責(zé)管理和存儲(chǔ)文件信息的軟件機(jī)構(gòu)稱(chēng)為文件管理系統(tǒng),簡(jiǎn)稱(chēng)文件系統(tǒng)。
2,文件系統(tǒng)可以做什么
從系統(tǒng)角度來(lái)看,文件系統(tǒng)是對(duì)文件存儲(chǔ)設(shè)備的空間進(jìn)行組織和分配,負(fù)責(zé)文件存儲(chǔ)并對(duì)存入的文件進(jìn)行保護(hù)和檢索的系統(tǒng)。具體地說(shuō),它負(fù)責(zé)為用戶(hù)建立文件,存入、讀出、修改、轉(zhuǎn)儲(chǔ)文件,控制文件的存取,當(dāng)用戶(hù)不再使用時(shí)撤銷(xiāo)文件等。
3,Linux文件系統(tǒng)層次簡(jiǎn)介

如圖1所示,文件系統(tǒng)從大的方面可以分為兩層:
- 用戶(hù)空間,如用戶(hù)使用的各種應(yīng)用程序
- 內(nèi)核空間,其又可以分為
- 文件管理系統(tǒng),包括虛擬文件系統(tǒng)(VFS)和具體文件系統(tǒng)。
- 設(shè)備驅(qū)動(dòng),包括緩沖區(qū)和設(shè)備驅(qū)動(dòng)。
虛擬文件系統(tǒng)(Virtual Filesystem Switch,簡(jiǎn)稱(chēng)VFS)簡(jiǎn)介:
虛擬文件系統(tǒng)(VFS)是對(duì)真實(shí)文件系統(tǒng)的抽象和軟件實(shí)現(xiàn),定義了所有文件系統(tǒng)都支持的、基本的 、 抽象的接口和數(shù)據(jù)結(jié)構(gòu)。
對(duì)內(nèi)(具體文件系統(tǒng)),允許同時(shí)使用不同的文件系統(tǒng),例如在不同文件系統(tǒng)之間復(fù)制、移動(dòng)文件;
對(duì)外(如其他內(nèi)核子系統(tǒng)及用戶(hù)的各種應(yīng)用程序),VFS提供統(tǒng)一的接口,使得程序開(kāi)發(fā)者不需要關(guān)注Linux實(shí)際使用的文件系統(tǒng)。
因此,Linux系統(tǒng)支持同時(shí)使用多個(gè)不同類(lèi)型的文件系統(tǒng)。具體文件系統(tǒng)(如ext4,xfs,btrfs等等)實(shí)現(xiàn)了VFS 定義的抽象接口和數(shù)據(jù)結(jié)構(gòu),將自身的諸如文件 、 目錄等概念在形式上與 VFS 的定義保持一致,在統(tǒng)一的接口和數(shù)據(jù)結(jié)構(gòu)下隱藏了具體的實(shí)現(xiàn)細(xì)節(jié)。
應(yīng)用程序從物理介質(zhì)讀取數(shù)據(jù)過(guò)程示意圖VFS的幾個(gè)重要數(shù)據(jù)結(jié)構(gòu):
- 超級(jí)塊(superblock):存放系統(tǒng)中已安裝的文件系統(tǒng)的所有信息。對(duì)基于磁盤(pán)的文件系統(tǒng),這類(lèi)對(duì)象通常對(duì)應(yīng)于存放在磁盤(pán)上的文件系統(tǒng)控制塊。也就是說(shuō),每個(gè)文件系統(tǒng)都有一個(gè)超級(jí)塊對(duì)象;
- 索引節(jié)點(diǎn)(index node,簡(jiǎn)稱(chēng)inode):存放對(duì)于具體文件的元數(shù)據(jù)信息(除了文件名)。每個(gè)文件都有一個(gè)索引節(jié)點(diǎn)對(duì)象,每個(gè)索引節(jié)點(diǎn)對(duì)象有一個(gè)索引節(jié)點(diǎn)號(hào),這個(gè)號(hào)唯一地標(biāo)識(shí)在某個(gè)文件系統(tǒng)中的指定文件;
- 目錄項(xiàng)(dentry):存放目錄項(xiàng)與對(duì)應(yīng)文件進(jìn)行鏈接的信息。VFS把每個(gè)目錄看作一個(gè)有若干個(gè)子目錄和文件組成的常規(guī)文件;
- 文件(file):存放打開(kāi)文件與進(jìn)程之間進(jìn)行交互的有關(guān)信息。這類(lèi)信息僅當(dāng)進(jìn)程訪(fǎng)問(wèn)文件存放于內(nèi)存中。
二,ext4文件系統(tǒng)簡(jiǎn)介
1,ext4文件系統(tǒng)管理結(jié)構(gòu)
ext4文件系統(tǒng)layout的官方說(shuō)明可以到這個(gè)頁(yè)面進(jìn)行了解:https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inline_Data,下面說(shuō)說(shuō)個(gè)人理解:

上圖簡(jiǎn)單介紹了ext4文件系統(tǒng)的布局:磁盤(pán)劃分為分區(qū),每個(gè)分區(qū)又劃分為N個(gè)塊組。在每個(gè)塊組中,又根據(jù)塊組的編號(hào)有不同的內(nèi)部結(jié)構(gòu)。
涉及到塊組(Block Group)組成元素簡(jiǎn)介:
-
引導(dǎo)塊
該磁盤(pán)分區(qū)的第一個(gè)塊,如果該分區(qū)裝了系統(tǒng),則記錄引導(dǎo)啟動(dòng)信息,用來(lái)引導(dǎo)啟動(dòng)該分區(qū)安裝的系統(tǒng),一般占用2KB。
BIOS+MBR啟動(dòng)的流程簡(jiǎn)述:
- BIOS:從固件中讀取BIOS及其設(shè)置,識(shí)別第一個(gè)可開(kāi)機(jī)設(shè)備的MBR位置
- MBR:MBR前446Byte是引導(dǎo)加載程序(Bootloader),
- 引導(dǎo)加載程序:Bootloader加載自己可識(shí)別的內(nèi)核文件,或者將管理區(qū)交給其他加載程序,其他加載程序再加載自己可識(shí)別的內(nèi)核
- 內(nèi)核(Kernel):管理調(diào)度更多操作系統(tǒng)功能
MBR和啟動(dòng)塊的關(guān)系
MBR和啟動(dòng)塊的關(guān)系
對(duì)上圖的幾點(diǎn)說(shuō)明:
- 每個(gè)分區(qū)都擁有自己的啟動(dòng)塊,但不是每個(gè)啟動(dòng)塊都裝載BootLoader。
- 實(shí)際可開(kāi)機(jī)的內(nèi)核文件是放置在各分區(qū)內(nèi)的。
- Bootloader只會(huì)認(rèn)識(shí)自己的系統(tǒng)分區(qū)內(nèi)的可開(kāi)機(jī)內(nèi)核文件,或者其他Bootloader。
- Bootloader可直接指向或者是間接將管理權(quán)轉(zhuǎn)交給另一個(gè)管理程序。
- 每個(gè)分區(qū)都有自己的啟動(dòng)塊,Bootloader可以安裝在MBR或啟動(dòng)塊上,Bootloader只會(huì)識(shí)別自己分區(qū)內(nèi)的可開(kāi)機(jī)內(nèi)核文件。
超級(jí)塊(Superblock)
The superblock records various information about the enclosing filesystem, such as block counts, inode counts, supported features, maintenance information, and more.
超級(jí)塊記錄關(guān)于封閉文件系統(tǒng)的各種信息,比如塊數(shù)量(已用和未用數(shù)量),inode數(shù)量(已用和未用數(shù)量),支持的功能特性,維護(hù)信息(比如分區(qū)上有多少個(gè)塊組,塊組的數(shù)據(jù)區(qū)和元數(shù)據(jù)區(qū),)等等。
If the sparse_super feature flag is set, redundant copies of the superblock and group descriptors are kept only in the groups whose group number is either 0 or a power of 3, 5, or 7. If the flag is not set, redundant copies are kept in all groups.
如果設(shè)置按照稀疏方式存儲(chǔ),則超級(jí)塊和塊組描述符的備份信息將只記錄在組號(hào)碼是0或者3、5、7的n冪的塊組中。如果不設(shè)置,則備份信息將記錄在所有塊組中(顯然備份信息將占用很多磁盤(pán)空間)。
一般只使用塊組0中的超級(jí)塊,因此也叫主超級(jí)塊。如果主超級(jí)塊信息損壞,可以從超級(jí)塊的備份信息中復(fù)制數(shù)據(jù)來(lái)修復(fù)。塊組描述符(Group Descriptor,簡(jiǎn)稱(chēng)GDT)
主要包含塊位圖,inode位圖和inode表位置,當(dāng)前空閑塊數(shù),inode數(shù)以及使用的目錄數(shù)(用于平衡各個(gè)塊組目錄數(shù))。每個(gè)塊組都對(duì)應(yīng)這樣一個(gè)描述符。
由于GDT對(duì)于定位文件系統(tǒng)的元數(shù)據(jù)非常重要,因此和超級(jí)塊一樣,也對(duì)其進(jìn)行了備份。GDT及其備份的內(nèi)容都是一樣的,所占?jí)K數(shù)也相同。預(yù)留GDT塊(Reserve GDT blocks)
在創(chuàng)建文件系統(tǒng)時(shí),為了便于將來(lái)擴(kuò)展文件系統(tǒng),在塊組描述符表后面分配預(yù)留的數(shù)據(jù)塊。塊位圖(Block bitmap):
Block Bitmap是用來(lái)標(biāo)識(shí)Block Group中的block使用情況,其中的每一位代表該Block Group中的一個(gè)block,如果是1則代表使用,如果是0則代表空閑。通過(guò)Block bitmap,可以快速知道該block group中每個(gè)block的使用情況。Inode位圖(Inode bitmap):
Inode位圖用于描述該塊組所管理的inode的分配狀態(tài),如果inode位圖中相應(yīng)位置為1,那么代表該inode已經(jīng)分配出去;否則可以使用。
inode:inode的全稱(chēng)是index-node,索引節(jié)點(diǎn)。
在Linux系統(tǒng)中,文件的數(shù)據(jù)分為元數(shù)據(jù)(metadata)和數(shù)據(jù)(data)兩類(lèi),其中存放元數(shù)據(jù)信息的區(qū)域就叫做inode,存放文件實(shí)際內(nèi)容的塊(block)被叫做數(shù)據(jù)塊(data block)。
inode中包含的信息主要有:
- inode編號(hào)(inode number)
- 文件的大小(size)
- 屬主(User ID)、屬組(Group ID)、權(quán)限(讀、寫(xiě)、執(zhí)行)
- 時(shí)間戳(共有三個(gè):ctime指inode上一次變動(dòng)的時(shí)間,mtime指文件內(nèi)容上一次變動(dòng)的時(shí)間,atime指文件上一次打開(kāi)的時(shí)間)、
- 鏈接數(shù)(硬鏈接次數(shù))
- 指向存放文件實(shí)際數(shù)據(jù)的block的塊指針(直接塊指針,最高三級(jí)間接塊指針)
注意:inode中
文件的
(原因下面會(huì)介紹)。
Inode結(jié)構(gòu)
Inode表(Inode table):
Inode表用于存儲(chǔ)inode信息。它占用一個(gè)或多個(gè)塊(為了有效的利用空間,多個(gè)inode存儲(chǔ)在一個(gè)塊中),其大小取決于文件系統(tǒng)創(chuàng)建時(shí)的參數(shù),由于inode位圖的限制,決定了其最大所占用的空間。數(shù)據(jù)塊(Data block):
元素1-7存放了ext4文件系統(tǒng)的元數(shù)據(jù),其他磁盤(pán)空間則用來(lái)存放文件真正的內(nèi)容,因此稱(chēng)為數(shù)據(jù)塊。
三,ext4文件系統(tǒng)文件管理簡(jiǎn)介
ext4文件系統(tǒng)(或者說(shuō)Linux系統(tǒng))內(nèi)部是使用inode number來(lái)識(shí)別文件的。任何文件都有其分區(qū)內(nèi)唯一的inode number,并通過(guò)塊指針與文件數(shù)據(jù)關(guān)聯(lián)。文件名只是為了便于人類(lèi)記憶和使用,給inode number起的“別稱(chēng)”或者“綽號(hào)”。
那么我們平時(shí)通過(guò)文件名來(lái)管理文件,是怎么實(shí)現(xiàn)的呢?文件名信息記錄在哪里?
Linux系統(tǒng)的哲學(xué)思想之一是“一切皆文件”,磁盤(pán)設(shè)備是文件(在我的另一篇blog《CentOS磁盤(pán)和分區(qū)簡(jiǎn)介》中有簡(jiǎn)要介紹),目錄也是文件。
目錄文件的結(jié)構(gòu)非常簡(jiǎn)單,就是一系列目錄項(xiàng)(dirent)的列表。每個(gè)目錄項(xiàng)由兩部分組成:目錄直接子文件的文件名,及其對(duì)應(yīng)的inode號(hào)碼。而根目錄/由Linux內(nèi)核直接管理并記錄其inode number。
Note:目錄只記錄直接子文件的文件名,及其對(duì)應(yīng)的inode號(hào)碼。
- Linux系統(tǒng)的哲學(xué)思想之一是“一切皆文件”,子文件可以是Linux支持的任何類(lèi)型文件,如普通文件、目錄、設(shè)備、管道、鏈接等等。
- 子文件的子文件,不會(huì)記錄在目錄中,因?yàn)椴皇?strong>直接子文件。
因此,我們可以很容易的通過(guò)根目錄及其子目錄,找到文件名對(duì)應(yīng)的inode number。再根據(jù)inode中指向數(shù)據(jù)塊的塊指針,找到文件內(nèi)容數(shù)據(jù)。
下面通過(guò)幾個(gè)例子來(lái)簡(jiǎn)單介紹管理文件的過(guò)程。
I,查找文件 /root/test/a.txt
- 通過(guò)內(nèi)核找到根目錄
/的inode number - 根據(jù)根目錄
/的inode number,到inode table中找到根目錄/的塊指針 - 通過(guò)塊指針找到根目錄
/的數(shù)據(jù)塊,根據(jù)其中的數(shù)據(jù)找到下級(jí)目錄/root/對(duì)應(yīng)的inode number - 根據(jù)
/root/對(duì)應(yīng)的inode number,到inode table中找到目錄/root/的元數(shù)據(jù)及塊指針 - 通過(guò)塊指針找到存放目錄
/root/的數(shù)據(jù)塊,根據(jù)其中數(shù)據(jù)找到/root/test/目錄對(duì)應(yīng)的inode number - 根據(jù)
/root/test/目錄對(duì)應(yīng)的inode number,到inode table中找到目錄/root/test/的元數(shù)據(jù)及塊指針 - 通過(guò)塊指針找到存放目錄
/root/test/的數(shù)據(jù)塊,根據(jù)其中數(shù)據(jù)找到文件/root/test/a.txt對(duì)應(yīng)的inode number - 根據(jù)文件
/root/test/a.txt對(duì)應(yīng)的inode number,到inode table中找到文件/root/test/a.txt的元數(shù)據(jù)及塊指針 - 通過(guò)塊指針找到存放文件
/root/test/a.txt的數(shù)據(jù)塊
至此完成尋找文件及其數(shù)據(jù)的過(guò)程。
根據(jù)執(zhí)行命令的不同,上面的過(guò)程可能也不一定都會(huì)走到步驟9,例如:
ls /root/test/b.txt,如果文件/root/test/b.txt不存在,那么到步驟6,在/root/test/目錄的數(shù)據(jù)中,會(huì)發(fā)現(xiàn)目錄項(xiàng)(dirent)中沒(méi)有文件b.txt的記錄,提示ls: 無(wú)法訪(fǎng)問(wèn)/root/test/b.txt: 沒(méi)有那個(gè)文件或目錄ls -i /root/test/a.txt,列出文件/root/test/a.txt的inode number,到步驟7就已經(jīng)獲取了需要的數(shù)據(jù)ls -l /root/test/a.txt,列出文件/root/test/a.txt的元數(shù)據(jù),元數(shù)據(jù)是存放在inode table中的,到步驟8就已經(jīng)獲取了需要的數(shù)據(jù)cat /root/test/a.txt,顯示文件/root/test/a.txt的數(shù)據(jù),這才需要走到步驟9并獲取數(shù)據(jù)塊中的文件數(shù)據(jù)

II,創(chuàng)建文件 /root/test/b.txt
- 掃描inode bitmap,找到一個(gè)空閑的inode,將其標(biāo)記為占用,獲取其對(duì)應(yīng)的inode number;
- 查找目錄
/root/test/的數(shù)據(jù)(過(guò)程參考I),并在其中添加一條目錄項(xiàng)(dirent)記錄,文件名為/root/test/b.txt,inode number在步驟1中已經(jīng)獲得; - 根據(jù)inode number,在inode table中找到該inode,記錄文件
/root/test/b.txt的部分元數(shù)據(jù),如inode number、權(quán)限等等; - 掃描block bitmap,找到可分配的空閑塊,標(biāo)記為占用,并在文件
/root/test/b.txt的元數(shù)據(jù)中記錄塊指針; - 在數(shù)據(jù)塊中寫(xiě)入文件數(shù)據(jù)。
III,刪除文件 /root/test/b.txt
- 查找文件
/root/test/b.txt使用的元數(shù)據(jù)信息(過(guò)程參考I); - 查找目錄
/root/test/的數(shù)據(jù)(過(guò)程參考I),并刪除文件/root/test/b.txt的目錄項(xiàng)(dirent)記錄; - 修改文件
/root/test/b.txt的元數(shù)據(jù),將其鏈接數(shù)-1; - 如果此時(shí)文件
/root/test/b.txt的鏈接數(shù)≤0,掃描block bitmap,將分配給文件的塊節(jié)點(diǎn)標(biāo)記為空閑; - 如果此時(shí)文件
/root/test/b.txt的鏈接數(shù)≤0,掃描inode bitmap,將其中對(duì)應(yīng)的節(jié)點(diǎn)標(biāo)記為空閑;
硬鏈接,軟鏈接簡(jiǎn)介
- 硬鏈接:
1.1 多個(gè)文件指向同一個(gè)inode,這些文件的inode number相同
1.2 硬鏈接表明文件可以通過(guò)不同的文件名訪(fǎng)問(wèn)
1.3 不能對(duì)目錄創(chuàng)建硬鏈接
1.4 硬鏈接不能跨分區(qū)
1.5 每多一個(gè)硬鏈接,inode的引用計(jì)數(shù)(鏈接數(shù))+1
- 軟鏈接(符號(hào)鏈接):
2.1 文件及其軟鏈接文件,使用的不是同一個(gè)inode,inode number不一樣;
2.2 軟鏈接文件的實(shí)際數(shù)據(jù)是另一個(gè)文件的路徑,是一個(gè)字符串,軟鏈接文件的大小為該字符串的長(zhǎng)度;
2.3 可以對(duì)目錄創(chuàng)建軟鏈接
2.4 軟鏈接可以跨分區(qū)
2.5 增加文件軟鏈接,不會(huì)增加inode的引用計(jì)數(shù)


