System plików NTFS
Zbyszek Skowron
21 grudnia 2005
Wprowadzenie
Podstawowe możliwości systemu plików NTFS:
- System uprawnień dla plików i katalogów.
- Kompresja plików.
- Pliki rzadkie (sparse files).
- Linki symbliczne do katalogów i linki twarde.
- Quoty.
- Szyfrowanie (EFS - Encoding File System).
- Journalling.
Podstawowe cechy
- Wolumin NTFS jest logicznie podzielony na klastry składające się z pewnej
stałej liczby fizycznych sektorów dysku.
Pozwalają na uniezależnienie struktury
systemu plików od fizycznych właściwości dysku.
- Wszystkie metadane są chronione przed rozspójnieniem (przez redundancję i journalling).
- Zwykłe dane nie są chronione.
- Wszystkie dane na dysku, łącznie z tablicą plików, journalem, boot sektorem i innymi metadanymi,
są trzymane w zwykłych plikach.
- Wszystkie informacje o pliku, włącznie z jego zawartością, są zapisane w jednolity sposób
(w atrybutach).
Ograniczenia i rozmiary klastrów
Ograniczenia systemu NTFS i jego implementacji w systemie Windows są różne:
|
NTFS |
Windows |
Numery klastrów |
64-bitowe |
32-bitowe |
Maks. rozmiar klastra |
64 KB |
64 KB |
Maks. wielkość woluminu |
16 EB |
256 TB |
Maks. wielkość pliku |
16 EB |
16 TB |
Maks. liczba plików |
232-1 |
232-1 |
Domyślne wielkości klastrów dla woluminów NTFS:
Rozmiar woluminu |
Wielkość klastra |
≤ 512MB |
512 B |
≤ 1GB |
1 KB |
≤ 2GB |
2 KB |
> 2GB |
4 KB |
Zastosowanie małych klastrów w systemie NTFS pozwala oszczędzić miejsce na dysku.
Atrybuty i stumienie
- Wszystkie dane związane z plikiem (nazwa, właściciel, czasy dostępu, zawartość itp.) są trzymane
w tzw. atrybutach.
- Każdy atrybut jest po prostu ciągiem bajtów, z opcjonalną nazwą.
- Zawartość pliku jest trzymana w nienazwanym atrybucie $DATA. Dodatkowe stumienie danych są trzymane w
nazwanych atrybutach $DATA.
- Każdy strumień ma swój rozmiar, rozmiar zaalokowany, wielkość zainicjalizowanych danych itp.
Przykład użycia strumieni:
Program
Windows Explorer używa strumienia
Summary Information do zapisania informacji
o autorze pliku, tytule, temacie itp. (
File>Properties>Summary
)
Przegląd atrybutów
$STANDARD_INFORMATION |
flagi takie jak as read-only, archive itp.; czasy utworzenia, dostępu, modyfikacji;
liczba dowiązań z katalogów (hard link count); właściciel
|
$FILE_NAME |
nazwa pliku (w Unicode); plik może mieć wiele nazw (np. długą nazwę i wersję 8.3)
|
$DATA |
poszczególne strumienie danych (jeden nienazwany i dowolna liczba nazwanych)
|
$OBJECT_ID |
unikalny, 64-bajtowy identyfikator pliku (dolne 16 bajtów identyfikuje wolumin);
NTFS pozwala na wyszukiwanie plików po tym atrybucie (używane przez link-tracking)
|
$ATTRIBUTE_LIST |
lista atrybutów z ich położeniem - używana, gdy atrybuty nie mieszczą się w jednym rekordzie
tablicy MFT (o niej za chwilę)
|
$EFS |
zawiera dane o szyfrowaniu pliku, m.in. klucze potrzebne do ich odszyfrowania
|
$REPARSE_POINT |
zawiera reparse-tag i dodatkowe dane; służy m.in. do implementacji linków symbolicznych
i punktów montowania
|
Metadane w systemie NTFS
Struktura i właściwości woluminu NTFS są definiowane przez następujące pliki z metadanymi:
$Mft |
Master File Table - plik definiujący rozmieszczenie wszyskich plików na dysku
(także samego $Mft!). Jest umieszczany przy początku dysku. |
$MftMirr |
Kopia pierwszych 16 rekordów z MFT (zawierających informacje o plikach z metadanymi).
Jest umieszczany przy środku dysku. |
$LogFile |
Plik journala. |
$Volume |
Zawiera informacje o nazwie i typie woluminu. |
$AttrDef |
Zawiera definicje atrybutów (m.in. ich nazwy i numery). |
\ |
Katalog główny woluminu. |
$Bitmap |
Mapa zajętości klastrów na dysku (jeden bit na klaster). |
$Boot |
Boot sektor (pierwsze 16 sektorów) - zawiera położenie MFT i boot record. |
$BadClus |
Plik składający się z zepsutych klastrów. Ponieważ każdy taki klaster jest
do niego doalokowywany, to nie może zostać użyty przez inny plik. |
$Secure |
Trzyma informacje o prawach dostępu do plików. |
$UpCase |
Tablica mapująca małe litery na wielkie. |
$Extend |
Katalog z pozostałymi plikami specjalnymi (jak $Quota, $ObjID, $UsnJrnl, $Reparse). |
Master File Table
- Klastry na dysku mają przyporządkowane kolejne numery począwszy od 0 (Logical Cluster Numbers - LCN).
- Klastry każdego strumienia danych są podobnie ponumerowane (Virtual Cluster Numbers - VCN).
- Master File Table jest plikiem zawierającym informacje o atrybutach plików i ich położeniu
(mapowaniu VCN na LCN).
- MFT składa się z rekordów po 1 KB - jeden lub więcej na plik.
- Każdy rekord zawiera następujące po sobie atrybuty.
- Atrybut zaczyna się nagłówkiem. Jeśli dane atrybutu są niewielkie, umieszczane są po nagłówku
(atrybut jest resident). Gdy danych jest więcej, alokowane są dla nich klastry poza MFT
(atrybut nonresident).
Master File Table, cd.
- Atrybuty nonresident mają w nagłówku wypisane klastry, w których zostały umieszczone ich dane:
- Mapowanie VCN na LCN jest zapisane w seriach. Każda seria to numer klastra na dysku (LCN), odpowiadającego mu
numeru klastra danych (VCN), oraz liczba kolejnych klastrów należących do serii
Master File Table, cd. 2
- Gdy w rekordzie pliku w MFT zabraknie miejsca na nagłówki atrybutów, dla pliku zostają przydzielone
dodatkowe rekordy w MFT, a w rekordzie bazowym zostaje założony nowy atrybut: $ATTRIBUTE_LIST.
Zawiera on listę pozostaych atrybutów pliku oraz informację o ich położeniu w innych rekordach MFT.
- Ponieważ $Mft jest takim samym plikem jak inne, to może zostać pofragmentowany. Aby temu zapobiec
NTFS definiuje MFT-Zone - obszar dysku wokoło pliku $Mft, przeznaczony na jego powiększenie.
Klastry z MFT-Zone mogą zostać zaalokowane na inne pliki tylko wtedy, gdy na dysku zaczyna
brakować miejsca.
Pliki skompresowane
- Plik podlegający automatycznej kompresji dzielony jest na 16-klastrowe kawałki.
- Każdy kawałek kompresowany jest oddzielnie.
- Jeśli skompresuje się on do mniej niż 16 klastrów jest zapisywany skompresowany, wpw.
jest zapisany rozkompresowany.
- Przykład pliku skompresowanego:
Pliki rzadkie i małe
- Pliki w systemie NTFS mogą mieć zaalokowanych mniej klastrów, niż wynikałoby to z ich rozmiaru.
Niezaalokowane klastry mają swoje numery wirtualne (VCN), ale nie mają numerów logicznych (LCN).
Przy odczycie są traktowane jak zawierające same zera.
Przy zapisie, w niewidoczny dla użytkownika sposób, alokowane są dla nich klastry logiczne.
- Jeśli plik jest dostatecznie mały, żeby jego atrybut $DATA zmieścił się w rekordzie w MFT, to
nie są dla niego alokowane żadne dodatkowe klastry.
Oszczędza się w ten sposób miejsce i zwiększa szybkość dostępu do pliku.
Katalogi
- Katalogi trzymają informacje o plikach w nich zawartych w atrybucie $INDEX_ROOT.
- Oprócz refernecji do rekordów plików w MFT są tam też często używane atrybuty plików,
zduplikowane z MFT:
- nazwy plików,
- czasy utworzenia, ostaniego dostępu i modyfikacji,
- wielkość pliku.
- Referencje do plików w MFT są 64-bitowymi liczbami:
- 48 bitów to numer rekordu pliku w MFT,
- 16 bitów to licznik wykorzystywany do sprawdzania spójności danych, zwiększany
za każdym rzazem, gdy rekord zostaje użyty na nowy plik.
Małe katalogi
- Małe katalogi, podobnie jak małe pliki, mogą być zawarte całkowicie w swoim rekordzie w MFT.
Duże katalogi
- Pliki w dużych katalogach są indeksowane i sortowane po nazwie.
- Indeksy są zaimplementowane jako B+ - drzewa, z korzeniem umieszczonym w atrybucie $INDEX_ROOT.
- Kolejne węzły drzewa (index-buffers) są alokowane w razie konieczności, a ich położenie
jest zapisywane w atrybucie $INDEX_ALLOCATION.
- Dodatkowy atrybut $BITMAP określa które klastry w węzłach drzewa są jeszcze wolne.
Journal
-
Jedną z najważniejszych cech systemu plików NTFS jest jego niezawodność.
- Jedynym sposobem na rozspójnienie go jest uszkodzenie dysku.
- Niezawodność ta jest zapewniona przez zastosowanie jouralling-u.
-
System NTFS ochrania w ten sposób tylko metadane definiujące strukturę woluminu oraz
prawa dostępu.
- Dane w plikach nie podlegają journalling-owi i mogą być stracone np. w przypadku
utraty zasilania.
Transakcje
- Wszystkie zmiany struktury woluminu, np.:
- zmiana drzewa katalogów,
- utworzenie pliku,
- zmiana rozmiaru pliku,
organizowane są w transakcje.
- Transakcje mogą składać się z pewnej liczby podoperacji, a zakończone są zawsze operacją commit.
- NTFS gwarantuje wykonanie całych transakcji atomowo.
Zasada działania journala
Aby journal był wiarygodny zapis danych musi się odbywać odpowiedniej kolejności:
- NTFS zapisuje transakcję w kopii log'a w pamięci.
- NTFS modyfikuje wolumin w pamięci.
- Cache manager zapisuje log na dysk.
- Cache manager zapisuje modyfikacje woluminu na dysk.
Dzięki temu plik journalla zawsze
wyprzedza faktyczną modyfikację struktury woluminu.
Ponadto driver NTFS co kilka sekund zapisuje do log'a
tablice niedokończonych transakcji i niezaaplikowanych podoperacji, oraz
tzw. checkpoint record zawierający ich położenie i informacje o tym,
jak daleko w log'u trzeba się wrócić aby rozpocząć przywracanie spójności.
Undo i Redo
- Każda podoperacja transakcji zawiera informację o sposobie zaaplikowania jej do systemu plików,
oraz o sposobie cofnięcia jej.
- Operacje Undo i Redo muszą być tak skonstruowane, aby mogły być wykonane wiele razy i nie
rozspójniły woluminu.
- Przykład fragmentu pliku $LogFile:
Przywracanie spójności
W przypadku, gdy wskutek awarii systemu część danych nie została zapisana na dysk, journal zawiera
informacje o przerwanych transakcjach. Przywracanie spójności odbywa się w trzech fazach:
1. Analiza
- Odczytanie z LFS start area pozycji ostatniego checkpoint record-u.
1. Analiza, cd.
- Odczytanie tablic przerwanych transakcji i niedokończonych operacji:
- Przeskanowanie log'a dalej w poszukiwaniu dalszych rekordów zmian.
- Ustalenie najstarszego rekordu od którego ma się zacząć przywracanie.
2. Redo
- Skanowanie log'a od rekordu od którego ma się zacząć przywracanie do przodu.
- Aplikowanie wszystkich napotkanych transakcji.
3. Undo
- Skanowanie log'a od końca do rekordu od którego zaczęło się przywracanie.
- Wycofywanie wszystkich transakcji, które nie były zakończone operacją commit.
Po tym kroku wolumin jest przywrócony do spójnego stanu.
Uprawnienia do plików
- W systemie NTFS każdy plik i katalog ma przypisany Deskryptor Uprawnień, opisujący
uprawnienia do niego dla poszczególnych użytkowników.
- Deskryptory te są zapisane w atrybucie $SDS pliku $Secure.
- Plik $Secure ma również atrybut $SII zawierający indeks deskryptorów według ich numerów,
oraz atrybut $SDH zawierający indeks deskryptorów według ich hash'a.
- Podczas dostępu do pliku w celu znalezienia odpowiedniego deskryptora używany jest numer
deskryptora z atrybutu $STANDARD_INFORMATION pliku w połączeniu z indeksem $SII.
- Podczas ustawiania deskryptora dla pliku używany jest indeks $SDH w celu wyeliminowania
identycznych deskryptorów w tablicy $SDS.
Uprawnienia do plików: plik $Secure
Koniec
-
Niniejsza prezentacja została przygotowana na podstawie książki "Microsoft Windows Internals"
Marka E. Russinovich'a i Davida A. Solomona.
Zbyszek Skowron, zs210995@zodiac.mimuw.edu.pl