一,Linux文件系統(tǒng)
1,文件系統(tǒng)是什么
- 文件系統(tǒng)是操作系統(tǒng)用于明確存儲設備(常見的有磁盤既绕,固態(tài)硬盤等)或分區(qū)上的文件的方法和數(shù)據(jù)結(jié)構(gòu),即在存儲設備上組織文件的方法涮坐。
- 操作系統(tǒng)中負責管理和存儲文件信息的軟件機構(gòu)稱為文件管理系統(tǒng)凄贩,簡稱文件系統(tǒng)。
2袱讹,文件系統(tǒng)可以做什么
從系統(tǒng)角度來看疲扎,文件系統(tǒng)是對文件存儲設備的空間進行組織和分配,負責文件存儲并對存入的文件進行保護和檢索的系統(tǒng)捷雕。具體地說椒丧,它負責為用戶建立文件,存入救巷、讀出壶熏、修改、轉(zhuǎn)儲文件浦译,控制文件的存取棒假,當用戶不再使用時撤銷文件等。
3精盅,Linux文件系統(tǒng)層次簡介
如圖1所示淆衷,文件系統(tǒng)從大的方面可以分為兩層:
- 用戶空間,如用戶使用的各種應用程序
- 內(nèi)核空間渤弛,其又可以分為
- 文件管理系統(tǒng)祝拯,包括虛擬文件系統(tǒng)(VFS)和具體文件系統(tǒng)。
- 設備驅(qū)動她肯,包括緩沖區(qū)和設備驅(qū)動佳头。
虛擬文件系統(tǒng)(Virtual Filesystem Switch,簡稱VFS)簡介:
虛擬文件系統(tǒng)(VFS)是對真實文件系統(tǒng)的抽象和軟件實現(xiàn)晴氨,定義了所有文件系統(tǒng)都支持的康嘉、基本的 、 抽象的接口和數(shù)據(jù)結(jié)構(gòu)籽前。
對內(nèi)(具體文件系統(tǒng))亭珍,允許同時使用不同的文件系統(tǒng)敷钾,例如在不同文件系統(tǒng)之間復制、移動文件肄梨;
對外(如其他內(nèi)核子系統(tǒng)及用戶的各種應用程序)阻荒,VFS提供統(tǒng)一的接口,使得程序開發(fā)者不需要關(guān)注Linux實際使用的文件系統(tǒng)众羡。
因此侨赡,Linux系統(tǒng)支持同時使用多個不同類型的文件系統(tǒng)。具體文件系統(tǒng)(如ext4粱侣,xfs羊壹,btrfs等等)實現(xiàn)了VFS 定義的抽象接口和數(shù)據(jù)結(jié)構(gòu),將自身的諸如文件 齐婴、 目錄等概念在形式上與 VFS 的定義保持一致油猫,在統(tǒng)一的接口和數(shù)據(jù)結(jié)構(gòu)下隱藏了具體的實現(xiàn)細節(jié)。
VFS的幾個重要數(shù)據(jù)結(jié)構(gòu):
- 超級塊(superblock):存放系統(tǒng)中已安裝的文件系統(tǒng)的所有信息柠偶。對基于磁盤的文件系統(tǒng)情妖,這類對象通常對應于存放在磁盤上的文件系統(tǒng)控制塊。也就是說嚣州,每個文件系統(tǒng)都有一個超級塊對象鲫售;
- 索引節(jié)點(index node,簡稱inode):存放對于具體文件的元數(shù)據(jù)信息(除了文件名)该肴。每個文件都有一個索引節(jié)點對象情竹,每個索引節(jié)點對象有一個索引節(jié)點號,這個號唯一地標識在某個文件系統(tǒng)中的指定文件匀哄;
- 目錄項(dentry):存放目錄項與對應文件進行鏈接的信息秦效。VFS把每個目錄看作一個有若干個子目錄和文件組成的常規(guī)文件;
- 文件(file):存放打開文件與進程之間進行交互的有關(guān)信息涎嚼。這類信息僅當進程訪問文件存放于內(nèi)存中阱州。
二,ext4文件系統(tǒng)簡介
1法梯,ext4文件系統(tǒng)管理結(jié)構(gòu)
ext4文件系統(tǒng)layout的官方說明可以到這個頁面進行了解:https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inline_Data苔货,下面說說個人理解:
上圖簡單介紹了ext4文件系統(tǒng)的布局:磁盤劃分為分區(qū),每個分區(qū)又劃分為N個塊組立哑。在每個塊組中夜惭,又根據(jù)塊組的編號有不同的內(nèi)部結(jié)構(gòu)。
涉及到塊組(Block Group)組成元素簡介:
-
引導塊
該磁盤分區(qū)的第一個塊铛绰,如果該分區(qū)裝了系統(tǒng)诈茧,則記錄引導啟動信息,用來引導啟動該分區(qū)安裝的系統(tǒng)捂掰,一般占用2KB敢会。
BIOS+MBR啟動的流程簡述:
- BIOS:從固件中讀取BIOS及其設置曾沈,識別第一個可開機設備的MBR位置
- MBR:MBR前446Byte是引導加載程序(Bootloader),
- 引導加載程序:Bootloader加載自己可識別的內(nèi)核文件鸥昏,或者將管理區(qū)交給其他加載程序塞俱,其他加載程序再加載自己可識別的內(nèi)核
- 內(nèi)核(Kernel):管理調(diào)度更多操作系統(tǒng)功能
MBR和啟動塊的關(guān)系
對上圖的幾點說明:
- 每個分區(qū)都擁有自己的啟動塊,但不是每個啟動塊都裝載BootLoader互广。
- 實際可開機的內(nèi)核文件是放置在各分區(qū)內(nèi)的敛腌。
- Bootloader只會認識自己的系統(tǒng)分區(qū)內(nèi)的可開機內(nèi)核文件卧土,或者其他Bootloader惫皱。
- Bootloader可直接指向或者是間接將管理權(quán)轉(zhuǎn)交給另一個管理程序。
- 每個分區(qū)都有自己的啟動塊尤莺,Bootloader可以安裝在MBR或啟動塊上旅敷,Bootloader只會識別自己分區(qū)內(nèi)的可開機內(nèi)核文件。
超級塊(Superblock)
The superblock records various information about the enclosing filesystem, such as block counts, inode counts, supported features, maintenance information, and more.
超級塊記錄關(guān)于封閉文件系統(tǒng)的各種信息颤霎,比如塊數(shù)量(已用和未用數(shù)量)媳谁,inode數(shù)量(已用和未用數(shù)量),支持的功能特性友酱,維護信息(比如分區(qū)上有多少個塊組晴音,塊組的數(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.
如果設置按照稀疏方式存儲锤躁,則超級塊和塊組描述符的備份信息將只記錄在組號碼是0或者3、5或详、7的n冪的塊組中系羞。如果不設置,則備份信息將記錄在所有塊組中(顯然備份信息將占用很多磁盤空間)霸琴。
一般只使用塊組0中的超級塊椒振,因此也叫主超級塊。如果主超級塊信息損壞梧乘,可以從超級塊的備份信息中復制數(shù)據(jù)來修復澎迎。塊組描述符(Group Descriptor,簡稱GDT)
主要包含塊位圖选调,inode位圖和inode表位置夹供,當前空閑塊數(shù),inode數(shù)以及使用的目錄數(shù)(用于平衡各個塊組目錄數(shù))学歧。每個塊組都對應這樣一個描述符罩引。
由于GDT對于定位文件系統(tǒng)的元數(shù)據(jù)非常重要,因此和超級塊一樣枝笨,也對其進行了備份袁铐。GDT及其備份的內(nèi)容都是一樣的揭蜒,所占塊數(shù)也相同。預留GDT塊(Reserve GDT blocks)
在創(chuàng)建文件系統(tǒng)時剔桨,為了便于將來擴展文件系統(tǒng)屉更,在塊組描述符表后面分配預留的數(shù)據(jù)塊。塊位圖(Block bitmap):
Block Bitmap是用來標識Block Group中的block使用情況洒缀,其中的每一位代表該Block Group中的一個block瑰谜,如果是1則代表使用,如果是0則代表空閑树绩。通過Block bitmap萨脑,可以快速知道該block group中每個block的使用情況。Inode位圖(Inode bitmap):
Inode位圖用于描述該塊組所管理的inode的分配狀態(tài)饺饭,如果inode位圖中相應位置為1渤早,那么代表該inode已經(jīng)分配出去;否則可以使用瘫俊。
inode:inode的全稱是index-node鹊杖,索引節(jié)點。
在Linux系統(tǒng)中扛芽,文件的數(shù)據(jù)分為元數(shù)據(jù)(metadata)和數(shù)據(jù)(data)兩類骂蓖,其中存放元數(shù)據(jù)信息的區(qū)域就叫做inode,存放文件實際內(nèi)容的塊(block)被叫做數(shù)據(jù)塊(data block)川尖。
inode中包含的信息主要有:
- inode編號(inode number)
- 文件的大小(size)
- 屬主(User ID)登下、屬組(Group ID)、權(quán)限(讀空厌、寫庐船、執(zhí)行)
- 時間戳(共有三個:ctime指inode上一次變動的時間,mtime指文件內(nèi)容上一次變動的時間嘲更,atime指文件上一次打開的時間)筐钟、
- 鏈接數(shù)(硬鏈接次數(shù))
- 指向存放文件實際數(shù)據(jù)的block的塊指針(直接塊指針,最高三級間接塊指針)
注意:inode中文件的(原因下面會介紹)赋朦。
Inode表(Inode table):
Inode表用于存儲inode信息篓冲。它占用一個或多個塊(為了有效的利用空間,多個inode存儲在一個塊中)宠哄,其大小取決于文件系統(tǒng)創(chuàng)建時的參數(shù)壹将,由于inode位圖的限制,決定了其最大所占用的空間毛嫉。數(shù)據(jù)塊(Data block):
元素1-7存放了ext4文件系統(tǒng)的元數(shù)據(jù)诽俯,其他磁盤空間則用來存放文件真正的內(nèi)容,因此稱為數(shù)據(jù)塊承粤。
三暴区,ext4文件系統(tǒng)文件管理簡介
ext4文件系統(tǒng)(或者說Linux系統(tǒng))內(nèi)部是使用inode number來識別文件的闯团。任何文件都有其分區(qū)內(nèi)唯一的inode number,并通過塊指針與文件數(shù)據(jù)關(guān)聯(lián)仙粱。文件名只是為了便于人類記憶和使用房交,給inode number起的“別稱”或者“綽號”。
那么我們平時通過文件名來管理文件伐割,是怎么實現(xiàn)的呢候味?文件名信息記錄在哪里?
Linux系統(tǒng)的哲學思想之一是“一切皆文件”隔心,磁盤設備是文件(在我的另一篇blog《CentOS磁盤和分區(qū)簡介》中有簡要介紹)白群,目錄也是文件。
目錄文件的結(jié)構(gòu)非常簡單济炎,就是一系列目錄項(dirent)的列表川抡。每個目錄項由兩部分組成:目錄直接子文件的文件名辐真,及其對應的inode號碼须尚。而根目錄/
由Linux內(nèi)核直接管理并記錄其inode number。
Note:目錄只記錄直接子文件的文件名侍咱,及其對應的inode號碼耐床。
- Linux系統(tǒng)的哲學思想之一是“一切皆文件”,子文件可以是Linux支持的任何類型文件楔脯,如普通文件撩轰、目錄、設備昧廷、管道堪嫂、鏈接等等。
- 子文件的子文件木柬,不會記錄在目錄中皆串,因為不是直接子文件。
因此眉枕,我們可以很容易的通過根目錄及其子目錄恶复,找到文件名對應的inode number。再根據(jù)inode中指向數(shù)據(jù)塊的塊指針速挑,找到文件內(nèi)容數(shù)據(jù)谤牡。
下面通過幾個例子來簡單介紹管理文件的過程。
I姥宝,查找文件 /root/test/a.txt
- 通過內(nèi)核找到根目錄
/
的inode number - 根據(jù)根目錄
/
的inode number翅萤,到inode table中找到根目錄/
的塊指針 - 通過塊指針找到根目錄
/
的數(shù)據(jù)塊,根據(jù)其中的數(shù)據(jù)找到下級目錄/root/
對應的inode number - 根據(jù)
/root/
對應的inode number腊满,到inode table中找到目錄/root/
的元數(shù)據(jù)及塊指針 - 通過塊指針找到存放目錄
/root/
的數(shù)據(jù)塊套么,根據(jù)其中數(shù)據(jù)找到/root/test/
目錄對應的inode number - 根據(jù)
/root/test/
目錄對應的inode number流纹,到inode table中找到目錄/root/test/
的元數(shù)據(jù)及塊指針 - 通過塊指針找到存放目錄
/root/test/
的數(shù)據(jù)塊,根據(jù)其中數(shù)據(jù)找到文件/root/test/a.txt
對應的inode number - 根據(jù)文件
/root/test/a.txt
對應的inode number违诗,到inode table中找到文件/root/test/a.txt
的元數(shù)據(jù)及塊指針 - 通過塊指針找到存放文件
/root/test/a.txt
的數(shù)據(jù)塊
至此完成尋找文件及其數(shù)據(jù)的過程漱凝。
根據(jù)執(zhí)行命令的不同,上面的過程可能也不一定都會走到步驟9诸迟,例如:
ls /root/test/b.txt
茸炒,如果文件/root/test/b.txt
不存在,那么到步驟6阵苇,在/root/test/
目錄的數(shù)據(jù)中壁公,會發(fā)現(xiàn)目錄項(dirent)中沒有文件b.txt
的記錄,提示ls: 無法訪問/root/test/b.txt: 沒有那個文件或目錄
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,找到一個空閑的inode搪花,將其標記為占用遏片,獲取其對應的inode number;
- 查找目錄
/root/test/
的數(shù)據(jù)(過程參考I)撮竿,并在其中添加一條目錄項(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惨驶,找到可分配的空閑塊白热,標記為占用,并在文件
/root/test/b.txt
的元數(shù)據(jù)中記錄塊指針粗卜; - 在數(shù)據(jù)塊中寫入文件數(shù)據(jù)屋确。
III,刪除文件 /root/test/b.txt
- 查找文件
/root/test/b.txt
使用的元數(shù)據(jù)信息(過程參考I); - 查找目錄
/root/test/
的數(shù)據(jù)(過程參考I)攻臀,并刪除文件/root/test/b.txt
的目錄項(dirent)記錄焕数; - 修改文件
/root/test/b.txt
的元數(shù)據(jù),將其鏈接數(shù)-1刨啸; - 如果此時文件
/root/test/b.txt
的鏈接數(shù)≤0堡赔,掃描block bitmap,將分配給文件的塊節(jié)點標記為空閑设联; - 如果此時文件
/root/test/b.txt
的鏈接數(shù)≤0善已,掃描inode bitmap,將其中對應的節(jié)點標記為空閑离例;
硬鏈接换团,軟鏈接簡介
- 硬鏈接:
1.1 多個文件指向同一個inode,這些文件的inode number相同
1.2 硬鏈接表明文件可以通過不同的文件名訪問
1.3 不能對目錄創(chuàng)建硬鏈接
1.4 硬鏈接不能跨分區(qū)
1.5 每多一個硬鏈接宫蛆,inode的引用計數(shù)(鏈接數(shù))+1
- 軟鏈接(符號鏈接):
2.1 文件及其軟鏈接文件艘包,使用的不是同一個inode,inode number不一樣耀盗;
2.2 軟鏈接文件的實際數(shù)據(jù)是另一個文件的路徑想虎,是一個字符串,軟鏈接文件的大小為該字符串的長度袍冷;
2.3 可以對目錄創(chuàng)建軟鏈接
2.4 軟鏈接可以跨分區(qū)
2.5 增加文件軟鏈接磷醋,不會增加inode的引用計數(shù)