# 文件系統 > 文件是面向OS和麵向使用者而言的,對於人來說,音樂,圖片,文檔,游戲,軟體,郵件,等記錄信息的載體都被操作系統統稱為文件,而存儲在HDD(機械硬碟)和SSD(固態硬碟)里.因此文件是一種實體的抽象,而之所以文件需要文件名,是因為不同的文件需要進行相對應的區分,也就是文件名,而其中的 ...
文件系統
文件是面向OS和麵向使用者而言的,對於人來說,音樂,圖片,文檔,游戲,軟體,郵件,等記錄信息的載體都被操作系統統稱為文件,而存儲在HDD(機械硬碟)和SSD(固態硬碟)里.因此文件是一種實體的抽象,而之所以文件需要文件名,是因為不同的文件需要進行相對應的區分,也就是文件名,而其中的展開就是文件內容,本質上也就是一堆字元序列,而文件名常常是不通的,因此如何去管理這些文件名,就需要一個對應的目錄,就好比教務系統管理我們的信息一樣,因此這些不同的文件共同組成了目錄,而每個目錄其中的最小單位也就是每一個目錄項,他記載著每個文件地址或編號.
而我們使用者如何去進行基礎的讀寫創建刪除文件的操作,則需要文件系統的支持,而使用者與文件之間的這層薄膜就是虛擬文件系統
,用來幫我們實現介面去調用相應的操作執行我們的行為.
而對上層開發者及使用者來說:虛擬文件系統
就是對應的的執行介面.
那麼對下層的存儲設備來說:文件系統
就是以某種形式在存儲設備上保存和維護這這些文件的數據,而為了更好地統一使用虛擬文件系統
組織和管理文件系統,將存儲設備抽象為塊設備
,因此可以將存儲設備上的邏輯地址劃分為固定大小的塊
,這一點的設計和記憶體的設計劃分有著相似之處.
- 通常來說,塊是設備讀寫的最小單元,通常來說大小是512位元組或者4KB.每個存儲塊都會有一個相應的地址,被稱為
塊號
而如果想查看自己電腦的塊總數和相關的信息可以使用命令查看
- 這裡以WIN10為例:以管理員模式允許cmd輸入:
fsinfo ntfsinfo C:
輸出結果顯示:
NTFS Volume Serial Number : 0xacfc89e7fc89abe0
NTFS Version : 3.1
LFS Version : 2.0
Total Sectors : 791,466,638 (377.4 GB)
Total Clusters : 98,933,329 (377.4 GB)
Free Clusters : 51,237,504 (195.5 GB)
Total Reserved Clusters : 1,339,199 ( 5.1 GB)
Reserved For Storage Reserve : 1,328,585 ( 5.1 GB)
Bytes Per Sector : 512
Bytes Per Physical Sector : 512
Bytes Per Cluster : 4096
Bytes Per FileRecord Segment : 1024
Clusters Per FileRecord Segment : 0
Mft Valid Data Length : 1.12 GB
Mft Start Lcn : 0x00000000000c0000
Mft2 Start Lcn : 0x0000000000000002
Mft Zone Start : 0x0000000002f6e180
Mft Zone End : 0x0000000002f76aa0
MFT Zone Size : 137.13 MB
Max Device Trim Extent Count : 256
Max Device Trim Byte Count : 0xffffffff
Max Volume Trim Extent Count : 62
Max Volume Trim Byte Count : 0x40000000
Resource Manager Identifier : B20E52C3-85D6-11EA-A277-9CEBE83A74F8
- Bytes Per Cluster:4096 位元組,這表示每個塊的大小為 4KB。
- Total Clusters:98,933,329,表示總的塊數。
意味著我的系統塊的大小是4KB,同時需要註意,即使你創建的一個文件沒有超過塊的大小,依然會分配一個塊給你,這裡的分配其實和記憶體頁的分配類似,都會導致空間利用率不確定,也就是碎片的問題,不過磁碟的碎片是可以接受的,但同樣不宜將塊的大小定大.
1.基於inode的文件系統
前面對文件系統中每一個存儲塊的大小定義為4KB去存放這些文件,可是按照常理來說,很多文件的大小往往都不止4KB,比如一些圖片,音頻等,很容易都是MB,因此就需要幾千個4KB的塊去存,而像大電影那種GB的文件,就需要幾十萬甚至幾百萬個4KB的塊,而這些塊都需要與之對應的塊號,也就是類似地址一樣的東西來表示這些塊,也就是去表示這些文件,因此記錄這些塊號也需要開闢額外的記憶體空間,所以文件系統是如何解決這一龐大的開銷呢?
為了去記錄這些塊號,因此提出了一種磁碟結構:inode
:index node的簡寫,即索引節點,他記錄了每一個文件所對應的塊的塊號,即存儲索引.
而前面我們也顧及過一個問題,就是一個文件所占用的磁碟空間可能不止一個塊,即多個塊,這意味著需要多個indoe去記錄.
意味著indoe這種磁碟結構需要額外分配來記錄存儲索引,以免遇到更大的數據類型,需要更多的塊,因此如果通過預留的方式則可能會導致資源的浪費.因此,一種類似記憶體空間頁表的設計思想利用到了文件系統到中.
也就是採用多級,即分級的方法是來組織和存儲塊號
這樣最大的優點就是高級的索引塊是固定的,而不用在受限於數據的大小,即通過間接索引塊去記錄文件對應的塊號,自由地動態分配,且這種多級索引塊的方式提供了更大的定址範圍,如果只是簡簡單單的一級索引塊,假設字長為8位的情況下,可表示的範圍也就只有28 ,當然,實際上都是8位元組,甚至幾百位元組的情況下,不過多級索引的這種方式,無疑讓塊號可表示的範圍更長了,也就類似偏移地址的那種感覺.畢竟硬碟其實非常的大,相比於記憶體,其實這種塊號需要的表示範圍還是蠻大的,僅僅靠著一張inode去存儲這個塊號,明顯力不從心,而且這種多級的方式也更加利於管理.
- 在圖示中,我們還在inode中寫入了元數據這一項,其意義是處了存儲塊號之外,還有著其他的數據信息:
- 文件類型:指示文件是普通文件、目錄、符號鏈接等類型。
- 文件許可權:指定文件的訪問許可權,如讀、寫、執行許可權。
- 文件所有者:記錄文件的所有者用戶和用戶組。
- 文件大小:指示文件的大小,以位元組為單位。
- 創建時間和修改時間:記錄文件的創建時間和最後修改時間。
- 文件鏈接計數:指示有多少個目錄項指向該inode,用於維護文件的引用計數。
- 數據塊指針:用於指向文件數據所在的數據塊,包括直接塊指針、間接塊指針和二次間接塊指針等。
2.文件名與目錄
以上基於inode的文件系統的實現其面向的對象是OS內部本身,即用戶並不能通過塊號或者說去查找塊號去定位文件的位置,為了方便用戶,也就是通過每個inode號去和文件名映射一種對應關係,就跟網路中的功能變數名稱和IP一樣,人類不方便去記憶IP地址和inode號一樣,他們選擇了一種名字的方式去尋找和查找一樣.因此這些被映射的文件名就會被放在目錄
之中.
本著Linux的一切皆文件的想法,目錄本身也是一種特殊類型的文件,記錄著文件名和inode號的映射,同樣目錄也存在著多級也就是子目錄的情況下,因此這種結構就如同我們的文件夾一樣,可以去通過遞歸的形式,來組織的管理文件系統中的文件.而我們目錄里存放的這種結構則是目錄項,每個目錄下都代表著文件信息,比如文件名和對應的inode號等.
例如:在Linux下可以使用tree命令去查看目錄結構:
[root@iZf8ze1gd2ic6tea2rrf8dZ wwwroot]# tree
.
└── default
1 directory, 0 files
wwwroot下僅一個default文件夾,因此輸出如上
如果Linux中沒有tree命令,則執行:sudo yum install tree
(CentOS);
因此文件名與inode號之間這種映射被存放在目錄項里,而目錄則管理著這些目錄
在大多數文件系統中,目錄被存儲在特定的數據塊中,這些數據塊通常稱為目錄數據塊或目錄文件塊。每個目錄數據塊都包含了一系列的目錄項,每個目錄項對應一個文件或目錄,並記錄了其名稱和對應的Inode號。
因此,展開如圖所示:
3.硬鏈接與軟鏈接
硬鏈接
由於indoe是一個非負整數,他可以表示唯一的文件名,這意味著通過inode一定能找到一個文件,但文件名並不是存放在索引塊或者inode塊中的元數據,這意味著文件名其實更像是一種標識,因此可以出現多個文件名保持同一個inode號的情況出現.
例如:通過ln file1.txt file2.txt
創造一個文件兩個名字的,也就意味著有兩個目錄項,他們兩的inode號是相同的.
$ ln file1.txt file2.txt
我們可以使用 ls -i
命令查看文件的Inode號:
[root@iZf8ze1gd2ic6tea2rrf8dZ www]# ls -i file1 file2
1325159 file1 1325159 file2
而為了方便記錄有多少個目錄項指向inode,因此在元數據中保存著這個文件最原始的一些信息,包括有多個鏈接指向他,是不是很智能.
軟鏈接(符號鏈接)
軟鏈接是一種文件類型,他並不會指向inode號,而是通過文件的路徑去指向文件,其實本質是一個文件,而文件裡面存放的是路徑,因此他也有元數據和對應的目錄項
例如:通過ln -s target slink
來為target文件創造一個軟鏈接slink
[root@iZf8ze1gd2ic6tea2rrf8dZ www]# ln -s target slink
我們可以使用ls -l
命令查看文件的軟鏈接:
[root@iZf8ze1gd2ic6tea2rrf8dZ www]# ls -l slink
lrwxrwxrwx 1 root root 6 Jun 1 15:37 slink -> target
圖解的形式如下:
其實這種設計思想的落腳實現在很多地方都有所體現.比如JVM中位元組碼文件中的符號鏈接,本質上就是類的全限定名,也就是相對路徑,這種路徑最後被轉換成實際的物理記憶體,也就是直接鏈接
4.存儲佈局
為什麼要去理解存儲佈局,早在記憶體管理的部分,其實我們就參考過這種設計思想,將記憶體按段分成相應的數據段,代碼段,棧段,BSS段等,這種段的劃分其實就已經為記憶體劃分了區域,雖然面向的對象依然是OS.同樣硬碟也作為一種存儲設備,區域的劃分可以更加地有效地去管理存儲設備上的文件和數據.
因此,一個存儲設備中的記憶體區域可以大致被劃分為超級塊
,塊分配信息
,inode分配信息
,inode表
,文件數據塊
等區域.每當我們進行格式化操作的時候,文件系統就會去初始化每個區域的大小,佈局等信息
- 超級塊:這個結構非常的重要,他記錄著整個文件系統的全局元數據,比如文件系統類型:魔數,還有一些版本,文件系統管理空間的大小,因此超級塊實際記錄的是
文件系統
的相關信息,用來描述文件系統的屬性和結構的 - 塊分配信息:則是用來記錄每個塊的使用情況的,這種結構使用點陣圖則可以大大節省記憶體,和記憶體的跟蹤類似,利用
點陣圖
則可知道每一個塊的使用情況,1表示已經使用,0則表示無使用. - inode分配信息:跟塊分配信息其實差不多,只不過特定與inode(索引節點),因為是固定分配好的,所以存在有一些用了,有一些沒用的情況
- inode表:inode表則是一開始提到的基於inode的文件系統中的索引節點,inode分配信息也就是根據inode表裡來的,因此一般情況下,由文件系統已經初始化定好了大小.