借り初めのひみつきち

仮ブログです。

exFAT について

exFAT というファイルシステムがあります。
FAT ファイルシステムの次世代ファイルシステムとしてリムーバブルメディアなどに採用実績がありますが、仕様が公開されておらず特許が絡むために Microsoft 製以外の OS からはあまり使い勝手がよくありませんでした。

しかし、仕様が公開され、特許の条件も緩和されようとしているようです。

docs.microsoft.com

exFAT は名前の通り FAT を改良したファイルシステムで、以下のような FAT によく似た特徴があります。

  • クラスタという単位でセクタを管理しており、最初のクラスタ番号は2である
  • FAT というテーブルによりクラスタチェインを管理している
  • 32バイト単位のディレクトリエントリでファイルを管理している

一方で以下のような相違点もあります。

  • 空き領域はビットマップで管理されており、 FAT 上で管理されていないファイルが存在する
  • 8.3 ファイル名が存在せず、通常のファイルはディレクトリエントリを複数必要とする
  • FAT には存在しなかったメタデータ拡張機能が存在する

FAT はフロッピーディスクの時代に設計されたもので小容量ではそれなりにうまく動いていましたが、メディアが GB 単位の時代になってくると色々と不都合が増えてきました。 exFAT はより大きなメディア、特にソリッドステートメモリーでうまく扱えることを前提に設計されています。

クラスタ

FAT におけるクラスタとは、生のセクタを直接扱うと量が多すぎて管理が大変になるので、複数のセクタをまとめてクラスタという名前の論理セクタとして扱うことでトータルの論理セクタ数を減らして管理を楽にするための概念です。
よく使われるクラスタサイズとして 4KiB や 32KiB などがあります。4KiBはページングのページサイズ、32KiBはよくあるフラッシュメモリーのページサイズと一致するため管理の都合が良い数値です。

クラスタ単位でディスクアクセスすることでセクタ単位でアクセスするよりも高速で効率的なディスクアクセスが可能になります。
一方で、クラスタサイズはファイルの最小単位でもあり、1バイトでも内容のあるファイルはディスク上で最低1クラスタを占有するため、クラスタサイズが大きすぎると必ずしもディスクを効率的に扱えるとは限りません。

クラスタ番号は歴史的な事情で2から開始します。*1 クラスタ番号から実際のセクタ番号に変換する場合はオフセットを考慮する必要があります。

FAT とクラスタチェーン

クラスタサイズを超えるファイルを格納するには2つ以上のクラスタが必要です。
1番目のクラスタ番号はディレクトリエントリから辿れますが、2番目以降のクラスタを探す方法が別途必要になります。
この時 FAT 系ファイルシステムは FAT というテーブルを参照する事で2番目以降のクラスタを探します。

例えばクラスタ番号123のクラスタの次のクラスタを探す場合、 FAT テーブルの123番目の要素を調べ、そこに456とあった場合は次のクラスタは456と決めることができます。

FAT では FAT の要素のサイズによって FAT12FAT16FAT32 というバリエーションがありました。*2
exFAT は稀に FAT64 という俗称で呼ばれることがありますが FAT の要素サイズは 32bit となっています。

FAT ファイルシステムでは FAT テーブルはクラスタの利用状況を管理するためにも使い、 FAT テーブル上に 0 と記述されたクラスタは空き領域、 0xF...F7 と記述されたクラスタ不良セクタや予約セクタを含んでいるのでデータとして使用禁止、という風にクラスタを管理していました。

一方、exFAT では利用状況の管理には FAT テーブルを利用せずビットマップで管理しており、クラスタが連続していることが保証されている属性のファイルは FAT 上にクラスタチェーンを形成しません。
つまり、exFAT には FAT によるクラスタチェーンで管理しているファイルと FAT を利用しないファイルの2種類のファイルがあります。

これによるメリットは2つあります。
ビットマップは FAT テーブルに比べてサイズが小さいので空き領域を割り当てる検索処理が素早くできます。空き領域をビットマップで管理するのは他のファイルシステムでも割とよく使われる方法です。
また、ファイルアクセス時に毎回 FAT 上のクラスタチェーンを辿るのはコストがかかるため、クラスタチェーンを辿らなくても連続したクラスタにアクセスできることで高速化に寄与します。

exFAT におけるファイル管理は基本的には FAT 上にクラスタチェーンを生成しないように連続した領域を割り当て、どうしても断片化してしまった時に改めてクラスタチェーンを生成するのが効率的な管理になります。 exFAT という名前でありながら基本的には FAT を利用しないのが exFAT です。

ディレクトリエントリ

FAT も exFAT も32バイト単位のディレクトリエントリという構造体でファイルの情報を管理します。

FAT のディレクトリエントリは FAT12 の時代に設計されたもので、 FAT32 の時代になるとかなり無理のある使い方をしてすでに限界に近い状態でした。
当初、ファイル名は8.3形式の短いファイル名のみサポートしていましたが、その後特殊な属性のディレクトリエントリを繋げることで長いファイル名をサポートし、互換性のために短いファイル名と長いファイル名の2つでファイルを管理していました。

exFAT でもディレクトリエントリの基本サイズは32バイトですが、ディレクトリエントリの構造を大幅に変更することで FAT よりも多くの情報を含めることができるようになり、タイムスタンプの2秒問題などが改善しています。
通常のファイルは1つのディレクトリエントリに情報が収まりきらないため3つ以上のディレクトリエントリを繋げて使用します。
8.3形式のファイル名には対応しておらず、 FAT の長いファイル名と同等の制限の緩いファイル名を使うことができます。

また、細かい違いとして従来サブディレクトリに存在した「.」「..」という存在理由のよくわからないディレクトリエントリは exFAT のボリューム上には存在しません。

メタデータ、大文字テーブル

exFAT では従来の FAT ファイルシステムにはなかったメタデータが増えています。
例えば、先述の空き領域ビットマップはメタデータとして専用のディレクトリエントリがルートディレクトリにあります。

また、 exFAT の特徴的なメタデータとして大文字テーブルというものがあります。
FAT ファイルシステムはもともとファイル名を大文字で管理し、ファイルの検索は大文字小文字を区別しません。
exFAT では大文字に変換するためのテーブルがボリューム上のメタデータとして存在します。*3
大文字テーブルで変換したファイル名からハッシュ値を計算し、ディレクトリエントリのハッシュ値と比較することで大小文字を無視したファイルの検索が高速にできるのが他のファイルシステムにはないユニークな特徴となっています。この部分が特許に絡んでいた気がしますが、ソースを見つけることができませんでした。

ソリッドステートメモリーとの親和性

exFAT は先述のようにクラスタが連続しているファイルは FAT によるクラスタチェーンを経由せず高速にアクセスできます。
また、クラスタサイズやオフセットを調整してソリッドステートメモリーのページサイズと一致させることで効率の良いアクセスが可能になっています。
そのためにソリッドステートメモリーの特性を記述できる拡張属性が定義されています。

*1:なぜ2から始まるのかはよくわかりません

*2:実は FAT32 は要素サイズは 32bit ですが 32bit 全て使っている訳ではありません

*3:しかし仕様書によると内容は固定のようです...