NTFS檔案系統結構分析
在NTFS檔案系統中,檔案存取是按簇進行分配,一個簇必需是物理扇區的整數倍,而且總是2的整數次方。NTFS檔案系統並不去關心什麼是扇區,也不會去關心扇區到底有多大(如是不是512位元組),而簇大小在使用格式化程式時則會由格式化程式根據卷大小自動的進行分配。
檔案通過主檔案表格(MFT)來確定其在磁碟上的儲存位置。主檔案表格是一個對應的資料庫,由一系列的檔案記錄組成--卷中每一個檔案都有一個檔案記錄(對於大型檔案還可能有多個記錄與之相對應)。主檔案表格本身也有它自己的檔案記錄。
NTFS卷上的每個檔案都有一個64位(bit)稱為檔案引用號(File Reference Number,也稱檔案索引號)的唯一標識。檔案引用號由兩部分組成:一是檔案號,二是檔案順序號。檔案號為48位,對應於該檔案在MFT中的位置。檔案順序號隨著每次檔案記錄的重用而增加,這是為NTFS進行內部一致性檢查而設計的。
NTFS使用邏輯簇號(Logical Cluster Number,LCN)和虛擬簇號(Virtual Cluster Number,VCN)來進行簇的定位。LCN是對整個卷中所有的簇從頭到尾所進行的簡單編號。卷因子乘以LCN,NTFS就能夠得到卷上的物理位元組位移量,從而得到物理磁碟地址。VCN則是對屬於特定檔案的簇從頭到尾進行編號,以便於引用檔案中的資料。VCN可以映射成LCN,而不必要求在物理上連續。
NTFS的目錄只是一個簡單的檔案名稱和檔案引用號的索引,如果目錄的屬性列表小於一個記錄的長度,那麼該目錄的所有資訊都儲存在主檔案表格的記錄中,對於大於記錄的目錄則使用B+樹進行管理。
主檔案表格中的基本檔案記錄中有一個指標指向一個儲存非常駐索引緩衝--包括該目錄下所有下一級子目錄和檔案的外部簇,而B+樹結構便於大型目錄中檔案和子目錄的快速尋找。
在NTFS中,所有儲存在卷上的資料都包含在檔案中,包括用來定位和擷取檔案的資料結構,引導程式和記錄這個卷的記錄(NTFS中繼資料)的位元影像,這體現了NTFS的原則:磁碟上的任何事物都為檔案。在檔案中儲存一切使得檔案系統很容易定位和維護資料,而在NTFS中,卷中所有存放的資料均在一個叫做MFT的檔案記錄數組中,稱為主檔案表格(Master File Table),MFT是由進階格式化產生的。而MFT則由檔案記錄(File Record)數組構成。File Record的大小一般是固定的,不管簇的大小是多少,均為1KB,這個概念相當於Linux中的inode(i節點)。File Record在MFT檔案記錄數組中物理上是連續的,且從0開始編號。MFT僅供系統本身組織、架構檔案系統使用,這在NTFS中稱為中繼資料(metadata)。其中最基本的前16個記錄是作業系統使用的非常重要的中繼資料檔案。這些NTFS主檔案表格的重要的中繼資料檔案都是以$(貨幣符號)開始的名字,所以是隱藏檔案,在Windows 2000中不能使用dir命令(甚至加上/ah參數)像普通檔案一樣列出這些中繼資料檔案。實際上File System Driver(ntfs.sys)維護了一個系統變數NTFS Protect System Files用於隱藏這些中繼資料。但是微軟公司也提供了一個OEM TOOL,叫做NFI.EXE,用此工具可以轉儲NTFS主檔案表格的重要的中繼資料檔案(中繼資料:是儲存在卷上支援檔案系統格式管理的資料。它不能被應用程式來訪問,它只能為系統提供服務),使用NFI顯示結果如下:
C:/>nfi C: |MORE
而這些中繼資料檔案檔案是系統驅動程式裝配卷所必需的,WINDOWS 2000給每個分區賦予一個盤符並不表示該分區包含有WINDOWS 2000可以識別的檔案系統格式,如果一旦主檔案表格損壞,那麼該分區在WINDOWS 2000下是無法讀取的。為了使該分區能夠在WINDOWS 2000下能被識別,也就是必須首先建立WINDOWS 2000可以識別的檔案系統格式即主檔案表格,這可通過進階格式化該分區來完成。眾所周知,Windows以簇號來定位檔案在磁碟儲存的位置,在FAT格式的檔案系統中有關簇號的指標是包含在FAT表中的,而在NTFS中有關簇號的指標是包含在$MFT及$MFTMirr檔案中的。
NTFS元檔案
伴隨著以上這些新增功能的是更多的用於存放與功能相關的資料的元檔案。最後,在下面的表中羅列出NTFS5中所有的元檔案:
每個MFT記錄都對應著不同的檔案,如果一個檔案有很多屬性或是分散成很多片段,就很可能需要多個檔案記錄。這時,存放其檔案記錄位置的第一個記錄就叫做“基檔案記錄”(base file record)。
MFT中的第1個記錄就是MFT自身。由於MFT檔案本身的重要性,為了確保檔案系統結構的可靠性,系統專門為它準備了一個鏡像檔案($MftMirr),也就是MFT中的第2個記錄。
第3個記錄是記錄檔($LogFile)。該檔案是NTFS為實現可恢複性和安全性而設計的。當系統運行時,NTFS就會在記錄檔中記錄所有影響NTFS卷結構的操作,包括檔案的建立和改變目錄結構的命令,例如複製,從而在系統失敗時能夠恢複NTFS卷。
第4個記錄是卷檔案($Volume),它包含了卷名、被格式化的卷的NTFS版本和一個標明該磁碟是否損壞的標誌位(NTFS系統以此決定是否需要調用Chkdsk程式來進行修複)。
第5個記錄是屬性定義表($AttrDef,attribute definition table),其中存放了卷所支援的所有檔案屬性,並指出它們是否可以被索引和恢複等。
第6個記錄是根目錄(/),其中儲存了存放於該卷根目錄下所有檔案和目錄的索引。在訪問了一個檔案後,NTFS就保留該檔案的MFT引用,第二次就能夠直接進行對該檔案的訪問。
第7個記錄是位元影像檔案($Bitmap)。NTFS卷的分配狀態都存放在位元影像檔案中,其中每一位(bit)代表卷中的一簇,標識該簇是閒置還是已被分配了的,由於該檔案可以很容易的被擴大,所以NTFS的卷可以很方便的動態擴大,而FAT格式的檔案系統由於涉及到FAT表的變化,所以不能隨意的對分區大小進行調整。
第8個記錄是引導檔案($Boot),它是另一個重要的系統檔案,存放著Windows 2000/XP的引導程式碼。該檔案必須位於特定的磁碟位置才能夠正確地引導系統。該檔案是在Format程式運行時建立的,這正體現了NTFS把磁碟上的所有事物都看成是檔案的原則。這也意味著雖然該檔案享受NTFS系統的各種安全保護,但還是可以通過普通的檔案I/O操作來修改。
第9個記錄是壞簇檔案($BadClus),它記錄了磁碟上該卷中所有的損壞的簇號,防止系統對其進行分配使用。
第10個記錄是安全檔案($Secure),它儲存了整個卷的安全性描述元資料庫。NTFS檔案和目錄都有各自的安全性描述元,為了節省空間的,NTFS將具有相同描述符的檔案和目錄存放在一個公用檔案中。
第11個記錄為大寫檔案($UpCase,upper case file),該檔案包含一個大小寫字元轉換表。
第12個記錄是擴充中繼資料目錄($Extended metadata directory)。
第13個記錄是重解析點檔案($Extend/$Reparse)。
第14個記錄是變更日誌檔案($Extend/$UsnJrnl)。
第15個記錄是配額管理檔案($Extend/$Quota)。
第16個記錄是對象ID檔案($Extend/$ObjId)。
第17~23記錄是是系統保留記錄,用於將來擴充。
MFT的前16個中繼資料檔案是如此重要,為了防止資料的丟失,NTFS系統在該卷檔案儲存體部分的正中央對它們進行了備份,參見。
NTFS把磁碟分成了兩大部分,其中大約12%分配給了MFT,以滿足其不斷增長的檔案數量。為了保持MFT元檔案的連續性,MFT對這12%的空間享有獨佔權。餘下的88%的空間被分配用來隱藏檔。而剩餘磁碟空間則包含了所有的物理剩餘空間--MFT剩餘空間也包含在裡面。MFT空間的使用機制可以這樣來描述:當檔案耗盡了儲存空間時,Windows作業系統會簡單地減少MFT空間,並把它分配給檔案儲存體。當有剩餘空間時,這些空間又會重新被劃分給MFT。雖然系統儘力保持MFT空間的專用性,但是有時不得不做出犧牲。儘管MFT片段有時是無法忍受的,卻無法阻止它的發生。
那麼NTFS到底是怎麼通過MFT來訪問卷的呢?首先,當NTFS訪問某個卷時,它必須“裝載”該卷:NTFS會查看引導檔案(在圖中的$Boot中繼資料檔案定義的檔案),找到MFT的物理磁碟地址。然後它就從檔案記錄的資料屬性中獲得VCN到LCN的映射資訊,並儲存在記憶體中。這個映射資訊定位了MFT的運行(run或extent)在磁碟上的位置。接著,NTFS再開啟幾個中繼資料檔案的MFT記錄,並開啟這些檔案。如有必要NTFS開始執行它的檔案系統恢複操作。在NTFS開啟了剩餘的中繼資料檔案後,使用者就可以開始訪問該卷了。
檔案和目錄記錄
NTFS將檔案作為屬性/屬性值的集合來處理,這一點與其他檔案系統不一樣。檔案資料就是未命名屬性的值,其他檔案屬性包括檔案名稱、檔案擁有者、檔案時間標記等。顯示了一個用於小檔案的MFT記錄。
每個屬性由單個的流(stream)組成,即簡單的字元隊列。嚴格地說,NTFS並不對檔案進行操作,而只是對屬性流程進行讀寫。NTFS提供對屬性流程的各種操作:建立、刪除、讀取(位元組範圍)以及寫入(位元組範圍)。讀寫操作一般是針對檔案的未命名屬性的,對於已命名的屬性則可以通過已命名的資料流句法來進行操作。
一個檔案通常佔用一個檔案記錄。然而,當一個檔案具有很多項屬性值或很零碎的時候,就可能需要佔用一個以上的檔案記錄。這種情況下,第一個檔案記錄是其基本的檔案記錄,儲存有該檔案需要的其它檔案記錄的位置。小檔案和檔案夾(典型的如1500位元組或更少)將全部儲存在檔案的MFT記錄裡。
檔案夾記錄包括索引資訊,小檔案夾記錄完全儲存在MFT結構內,然而大的檔案夾則被組織成B+樹結構,用一個指標指向一個外部簇,該簇用來儲存那些MFT記憶體儲不了的檔案夾的屬性。
NTFS卷上檔案的常用屬性在下表中列出(並不是所有檔案都有所有這些屬性)。
常駐屬性與非常駐屬性
當一個檔案很小時,其所有屬性和屬性值可存放在MFT的檔案記錄中。當屬性值能直接存放在MFT中時,該屬性就稱為常駐屬性(resident attribute)。有些屬性總是常駐的,這樣NTFS才可以確定其他非常駐屬性。例如,標準資訊屬性和根索引就總是常駐屬性。
每個屬性都是以一個標準頭開始的,在頭中包含該屬性的資訊和NTFS通常用來管理屬性的資訊。該頭總是常駐的,並記錄著屬性值是否常駐、對於常駐屬性,頭中還包含著屬性值的偏侈量和屬性值的長度。
如果屬性值能直接存放在MFT中,那麼NTFS對它的訪問時間就將大大縮短。NTFS只需訪問磁碟一次,就可立即獲得資料;而不必像FAT檔案系統那樣,先在FAT表中尋找檔案,再讀出連續分配的單元,最後找到檔案的資料。
小檔案或小目錄的所有屬性,均可以在MFT中常駐。小檔案的未命名屬性可以包括所有檔案資料。建立一個小檔案如所示:
該檔案的內容
檔案屬性
如通過NFI查看檔案“建立 文字文件.txt”的檔案記錄號為36,顯示內容如下:
File 36
/建立 文字文件.txt
$STANDARD_INFORMATION (resident)
$FILE_NAME (resident)
$FILE_NAME (resident)
$DATA (resident)
從顯示內容可以看出檔案的全部屬性都是常駐屬性,包括DATA屬性,沒有非常駐屬性,所以,用WINHEX開啟MFT,查看該檔案記錄,有如的內容
小檔案的檔案記錄
小目錄的索引根屬性可以包括其中所有檔案和子目錄的索引。參見
小目錄的MFT記錄
大檔案或大目錄的所有屬性,就不可能都常駐在MFT中。如果一個屬性(如檔案資料屬性)太大而不能存放在只有1KB的MFT檔案記錄中,那麼NTFS將從MFT之外分配地區。這些地區通常稱為一個運行(run)或一個盤區(extent),它們可用來儲存屬性值,如檔案資料。如果以後屬性值又增加,那麼NTFS將會再分配一個運行,以便用來儲存額外的資料。值儲存在運行中而不是在MFT檔案記錄中的屬性稱為非常駐屬性(nonresident attribute)。NTFS決定了一個屬性是常駐還是非常駐的;而屬性值的位置對訪問它的進程而言是透明的。
當一個屬性為非常駐時,如大檔案的資料,它的頭部包含了NTFS需要在磁碟上定位該屬性值的有關資訊。顯示了一個儲存在兩個運行中的非常駐屬性。
儲存在兩個運行中的非常駐屬性
在標準屬性中,只有可以增長的屬性才是非常駐的。對檔案來說,可增長的屬性有資料、屬性列表等。標準資訊和檔案名稱屬性總是常駐的。
一個大目錄也可能包括非常駐屬性(或屬性部分),參見。在該例中,MFT檔案記錄沒有足夠空間來儲存大目錄的檔案索引。其中,一部分索引存放在索引根屬性中,而另一部分則存放在叫作“索引緩衝”(index buffer)的非常駐運行中。這裡,索引根、索引分配以及位元影像屬性都是簡化表示的,這些屬性將在後面詳細介紹。對目錄而言,索引根的頭及部分值應是常駐的。
大目錄的MFT記錄
當一個檔案(或目錄)的屬性不能放在一個MFT檔案記錄中,而需要分開分配時,NTFS通過VCN-LCN之間的映射關係來記錄運行(run)或盤區情況。LCN用來為整個卷中的簇按順序從0到n進行編號,而VCN則用來對特定檔案所用的簇按邏輯順序從0到m進行編號。顯示了一個非常駐資料屬性的運行所使用的VCN與LCN編號。
非常駐資料屬性的VCN
當該檔案含有超過2個運行時,則第三個運行從VCN8開始,資料屬性頭部含有前兩個運行VCN的映射,這便於NTFS對磁碟檔案分配的查詢。為了便於NTFS快速尋找,具有多個運行檔案的常駐資料屬性頭中包含了VCN-LCN的映射關係,參見
非常駐資料屬性的VCN-LCN映射
雖然資料屬性常常因太大而儲存在運行中,但是其他屬性也可能因MFT檔案記錄沒有足夠空間而需要儲存在運行中。另外,如果一個檔案有太多的屬性而不能存放在MFT記錄中,那麼第二個MFT檔案記錄就可用來容納這些額外的屬性(或非常駐屬性的頭)。在這種情況下,一個叫作“屬性列表”(attribute list)的屬性就加進來。屬性列表包括檔案屬性的名稱和類型代碼以及屬性所在MFT的檔案引用。屬性列表通常用於太大或太零散的檔案,這種檔案因VCN-LCN映射關係太大而需要多個MFT檔案記錄。具有超過200個啟動並執行檔案通常需要屬性列表。