目錄
一、EXT2文件系統
1、宏觀認識
2、塊組內部構成
2.1?Data Block
2.2?i節點表(Inode Table)
2.3?塊位圖(Block Bitmap)
2.4?inode位圖(Inode Bitmap)?
2.5?GDT(Group Descriptor Table)?
2.6?超級塊(Super Block)
3、目錄與文件名
4、路徑解析
5、路徑緩存
6、掛載分區?
7、文件名與inode映射實驗
8、inode和datablock映射
9、 問題總結
二、軟硬鏈接?
1、軟連接
2、硬鏈接
三、文件時間-ACM
四、文件系統總結?
一、EXT2文件系統
1、宏觀認識
# 所有的準備?作都已經做完,是時候認識下?件系統了。我們想要在硬盤上儲?件,必須先把硬盤格式化為某種格式的?件系統,才能存儲?件。?件系統的?的就是組織和管理硬盤中的?件。
# 在Linux 系統中,最常?的是 ext2 系列的?件系統。其早期版本為 ext2,后來?發展出 ext3 和 ext4。ext3 和 ext4 雖然對 ext2 進?了增強,但是其核?設計并沒有發?變化,我們仍是以較?的 ext2 作為演示對象。
#?ext2?件系統將整個分區劃分成若?個同樣??的塊組 (Block Group),如下圖所?。只要能管理?個分區就能管理所有分區,也就能管理所有磁盤?件。
# 上圖中啟動塊(Boot Block/Sector)的??是確定的,為1KB,由PC標準規定,?來存儲磁盤分區信息和啟動信息,任何?件系統都不能修改啟動塊。啟動塊之后才是ext2?件系統的開始。
?#?ext2?件系統會根據分區的??劃分為數個Block Group。?每個Block Group都有著相同的結構組成。
2、塊組內部構成
2.1?Data Block
#?數據區:存放?件內容,也就是?個?個的Block。根據不同的?件類型有以下?種情況:
- 對于普通?件,?件的數據存儲在數據塊中。
- 對于?錄,該?錄下的所有?件名和?錄名存儲在所在?錄的數據塊中,除了?件名外,ls -l命令看到的其它信息保存在該?件的inode中。
- Block 號按照分區劃分,不可跨分區
2.2?i節點表(Inode Table)
- 存放文件屬性如文件大小,所有者,最近修改時間等
- 當前分組所有inode屬性的集合
inode編號以分區為單位,整體劃分,不可跨分區
2.3?塊位圖(Block Bitmap)
Block Bitmap
中記錄著Data Block
中哪個數據塊已經被占用,哪個數據塊沒有被占用。
2.4?inode位圖(Inode Bitmap)?
- 每個bit表示一個
inode
是否空閑可用。
2.5?GDT(Group Descriptor Table)?
#?塊組描述符表,描述塊組屬性信息,整個分區分成多少個塊組就對應有多少個塊組描述符。每個塊組描述符存儲一個塊組的描述信息,如在這個塊組中從哪里開始是inode Table,從哪里開始是Data Blocks,空間的inode和數據塊還有多少個等等。塊組描述符在每個塊組的開頭都有一份拷貝。
- 塊組內的inode表的塊位置
- 塊組內的塊位圖和inode位圖的塊位置
- 塊組內已使用和空閑的塊數對inode數
- 塊組的塊分配策略信息
// 磁盤級blockgroup的數據結構
struct ext2_group_desc
{__le32 bg_block_bitmap; /* Blocks bitmap block */__le32 bg_inode_bitmap; /* Inodes bitmap block */__le16 bg_inode_table; /* Inodes table block */__le16 bg_free_blocks_count;/* Free blocks count */__le16 bg_free_inodes_count;/* Free inodes count */__le16 bg_used_dirs_count;/* Directories count */__le16 bg_pad;__le16 bg_reserved[3];
};
2.6?超級塊(Super Block)
#?存放?件系統本?的結構信息,描述整個分區的?件系統信息。記錄的信息主要有:bolck 和 inode的總量,未使?的block和inode的數量,?個block和inode的??,最近?次掛載的時間,最近?次寫?數據的時間,最近?次檢驗磁盤的時間等其他?件系統的相關信息。Super Block的信息被破壞,可以說整個?件系統結構就被破壞了。
- 文件系統的大小(總塊數)
- 每個塊的大小
- inode的大小和數量
- 塊組的數量
#?超級塊在每個塊組的開頭都有?份拷?(第?個塊組必須有,后?的塊組可以沒有)。 為了保證?件系統在磁盤部分扇區出現物理問題的情況下還能正常?作,就必須保證?件系統的super block信息在這種情況下也能正常訪問。所以?個?件系統的super block會在多個block group中進?備份,這些super block區域的數據保持?致。
3、目錄與文件名
?#?問題:那目錄呢?目錄如何存儲的呢?
# 目錄也是按照前面我們說的方式存儲的,也就是說目錄也有自己的inode,無非就是在inode結構體里面使用type標記位來區分,不管是目錄還是文件,其他都和文件一樣。
# 那目錄的內容存儲什么啊?即目錄文件的數據塊存儲什么呢?答案是文件名->inode映射關系。
#?所以在磁盤中保存文件就沒有目錄的概念,都是inode和數據,具體是文件還是目錄,可以通過inode區分。因為磁盤只認inode,所以我們今天打開一個code.cc一定是先找到文件所處的目錄然后根據code.cc,查找目錄映射關系的inode,再根據inode確定分區和分組,加載inode屬性內容。此時我們Is就看到文件屬性!
#?所以,訪問?件,必須打開當前?錄,根據?件名,獲得對應的inode號,然后進??件訪問。訪問?件必須要知道當前?作?錄,本質是必須能打開當前?作?錄?件,查看?錄?件的內容!
4、路徑解析
5、路徑緩存
?
6、掛載分區?
# 問題:我們有一個分區->格式化->能否使用這個分區了?答案是不能。我們可以通過Is /dev/vda* -l查看云服務器的磁盤,可以看到我們云服務器有3個/dev/vad分區,并且我們無法直接進入這個分區。為什么?因為我們的分區需要和一個特定目錄進行關聯,之后進入這個目錄就相當于進入這個分區。這也叫做把目錄和分區進行掛載!?接下來我們做一個試驗來理解:
# 這里我們命令相當于從/dev/zero這個文件里面讀取內容,然后把內容設置為0,寫入到指定文件disk.img里面,寫入塊大小為1M。分區就是一個磁盤空間,形成一個文件就相當于形成一個磁盤空間!所以這里我們就有一個disk.img的5M的文件!?
# 然后我們使用mkfs.ext4?命令格式化分區內容為ext4文件系統,寫入文件系統本質就是清空兩個位圖,然后給分區分組。可以看到我們分配了1280個inode、1280個blocks。此時他已經被我們格式化為一塊盤了。
# 然后此時我們使用 df-h 命令查看掛載情況,同時還有文件系統的使用率、分區大小等。發現我們的/dev/vda3 和根目錄掛載了,所以我只要登錄操作系統就會處在/dev/vda3分區。
# 然后我們可以使用 mount 命令,把分區掛載到 /mnt/mydisk 目錄里面。此時我們 df-h 查看,發現確實已經掛載上了。?
?#?所以此時我們在/mnt/mydisk 創建文件,就是在disk.img所在的分區里面創建文件了。
# 我們要取消掛載,就可以使用 umont 命令,然后再 rm disk.img 即可。
??
#?我們已經能夠根據inode號在指定分區找?件了,也已經能根據?錄?件內容,找指定的inode了,在指定的分區內,我們可以為所欲為了。可是:
#?問題:inode不是不能跨分區嗎?Linux不是可以有多個分區嗎?我怎么知道我在哪?個分區???
# 所以結論就是:
7、文件名與inode映射實驗
# 我們說目錄在磁盤上的數據塊保存的是文件名和inode的映射關系,現在我們寫了一份代碼,先調用opendir 打開一個文件目錄,然后調用 readdir 就可以使用一個文件的描述符,然后返回一個結構體,這個結構體包含目錄中文件的屬性相關信息,然后把里面包含的文件名和inode映射關系打印出來?。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>int main(int argc, char *argv[])
{if (argc != 2) {fprintf(stderr, "Usage: %s <directory>\n", argv[0]);exit(EXIT_FAILURE);}DIR *dir = opendir(argv[1]); // 系統調?,??查閱if (!dir) {perror("opendir");exit(EXIT_FAILURE);}struct dirent *entry;while ((entry = readdir(dir)) != NULL) { // 系統調?,??查閱// Skip the "." and ".." directory entriesif (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {continue;}printf("Filename: %s, Inode: %lu\n", entry->d_name, (unsigned long)entry->d_ino);}closedir(dir);return 0;
}
#?我們發現確實和我們 Is -li 查看到的文件名和inode是一樣的!說明我們的目錄內容就是保存文件名和inode的映射關系!?
8、inode和datablock映射
#?inode內部存在?__le32 i_block[EXT2_N_BLOCKS]; /* Pointers to blocks */,EXT2_N_BLOCKS =15,
就是用來進行inode和block映射的。這樣文件=內容+屬性,就都能找到了。
#?我們在ext2_inode上可以發現存在一個i_blocks數組,這個數組的大小是15,這個就是我們說的inode和數據塊的映射數組!
# 如果我們的數組只填寫數據塊編號的15*4kb=60kb,而平時我們的隨便一個文件都是M為單位的,60kb根本不夠看啊! 所以這個數組只有前12個位置存儲數據塊編號映射關系,后面三個存儲一級、二級、三級塊索引指針?。
#?一級索引指針指向一個4kb的block,這4kb的block不是直接存儲文件數據,而是存儲文件數據塊的地址。假設指針大小為4字節,就有了4kb/4字節=1024個數據塊索引。二級索引指向的就是一級索引,以此類推所以我們就可以擴展我們保存的數據塊索引!
9、 問題總結
#?通過上面的學習,我們就可以回答一下幾個問題:?
1. 如何理解創建一個空文件?
- 遍歷
inode Bitmap
,找到比特位為0的位置,申請一個未被使用的inode
。- 將
inode
表中找到對應的inode
, 并將文件的屬性信息填到inode
結構當中。- 將該文件的文件名和
inode
指針添加到目錄文件的數據塊當中。
2. 如何理解向文件寫入信息?
- 通過文件的inode編號找到對應的inode結構。
- 通過inode結構找到存儲該文件內容的數據塊,并將數據寫入數據塊。
- 若不存在數據塊或者申請的數據塊已經寫滿了,就需要遍歷block Bitmap找到一個空的塊號,并在數據區當中找到對應的空閑塊,再把數據寫入到數據塊當中,最后還需要建立數據塊和inode結構的對應關系。
3. 刪除文件做了些什么?
- 將該文件對應的
inode
在Inode map
當中設置為無效。- 將該文件申請過的
Data Block
在Block map
當中置為無效。
# 這也是我們為什么刪除一個軟件的速度比下載同一個軟件的速度快的多的原因。當然因為文件內容并沒有被刪除,所以我們可以在對應內容被其他文件內容覆蓋之前,通過一些技術手段復原已刪除文件。?
4. 如何理解目錄?
目錄也是一種文件,是文件就有對應的文件屬性與文件內容,其中對應的文件屬性就是我們的
inode
存儲的就是目錄的大小,目錄的擁有者等。而對應的文件內容存儲的就是該目錄下的文件名以及對應文件的inode
指針。
二、軟硬鏈接?
1、軟連接
# 軟鏈接又叫做符號鏈接,軟鏈接文件是一個獨立的文件,該文件有自己的inode
號,但是該文件只包含了源文件的路徑名,所以軟鏈接文件一般就是對應路徑文件的一種快捷訪問方式。其中在Windows
系統中,我們桌面上軟件圖標就是訪問對應程序的快捷方式,本質其實就是一個軟連接文件。
#?在Linux
中,我們可以通過指令ln -s 文件名 軟鏈接名
設置軟連接:
# 我們向code.c追加重定向,發現通過軟連接也可以查看code.c的內容,所以軟連接其實就是類似我們的快捷方式!
# 通過快捷方式就可以找到我們的可執行程序,而我們的快捷方式是一個獨立的文件,所以我們刪除快捷方式并沒有真正刪除軟件,所以我們軟連接也是一個獨立的文件,所以我們可以看到code.c和code-soft的inode不同!
# 并且我們也能通過指令unlink 軟連接名
取消對應的軟連接,并且如果一旦刪除軟連接所指向的文件,那么該軟連接文件也將毫無意義。?
2、硬鏈接
#?硬鏈接文件就是源文件的一個別名,它與源文件之間具有相同的inode
大小。一旦為某個文件建立硬鏈接,那么對應的硬鏈接數就會加1。
#?在Linux
中,我們可以通過指令ln 文件名 硬鏈接名
建立對應的硬鏈接,同樣我們也能通過unlink 硬鏈接名
取消對應的硬鏈接。
# 硬鏈接沒有獨立的inode
,并不是一個獨立的文件, 本質是在特定的目錄下,添加一個文件名和inode
編號的映射關系。?
??
三、文件時間-ACM
#?在Linux
中,我們可以使用指令stat 文件名
來查看對應文件的信息。
# 以下是對應關于文件時間的信息:
Access
: 文件最后被訪問的時間。Modify
: 文件內容最后的修改時間。Change
: 文件屬性最后的修改時間。?
# 當我們修改文件內容時,文件的大小一般也會隨之改變,所以一般情況下Modify的改變會影響Change一起改變,但修改文件屬性一般不會影響到文件內容,所以一般情況下Change的改變不會影響Modify的改變。
# 我們若是想將文件的這三個時間都更新到最新狀態,可以使用指令touch 文件名。
四、文件系統總結?
#?下???張圖總結,主要想從不同?度說明:
?