最終更新日 1999年8月17日
ひとつ上に戻ろう トップ・ページへ戻ろう

FAT FS (File Allocation Table File System)

概要

 FAT FSは1977年来DISK BASICから始まり、 以後MS-DOS、WindowsへとMicrosoft社の製品でサポートされ続けているファイルシステムだ。 またMicrosoft社の製品の市場占有率のため、他のOSでも多く対応されている。 なお、このページは「SUPER ASCII 1997年2月号」を参考文献とした。

FATの遍歴

 FAT FSは、ディスク領域をクラスタ単位で分け、そのクラスタに番号を割り付け管理する。 MS-DOSの初期では、その番号の大きさが12bitで、 2^12=4096個(実際は4085(FFF5h)個)のクラスタを管理することができた。 しかし、クラスタサイズは最大で32KBなので、32KB*4096=128MBまでの容量しか対応できない。 (FAT12)

 なので、(MS-DOS ver. 3.xのことはちょいと飛ばして) MS-DOS ver. 4.xではクラスタエントリの値を16bit、 65536個(これまた実際は65525(FFF5h)個)まで拡張して、 最大32KB*65536=2GBの容量まで対応できるようにした。(FAT16)

 だが、ディスクの容量は増え、2GBを越えるものも珍しくなくなってきた。 もちろんパーティションを切ればいいのだが、2GBのパーティションというのも窮屈で(末恐ろしいものだ)、 それだけではなくパーティションを1GB以上で切ると、 クラスタサイズは32KBになり(512MB以上1GB未満でも16KBだ)、 どんなに小さなファイルでも最低32KB領域を消費してしまう。 このことを回避するため、Windows 95 OSR2から、ディレクトリエントリが32bitに拡張された。 が、実際は28bitしか使われておらず、管理するクラスタ数も268435445(FFFFFF5h)個である。 (FAT32)


内部構造

 ここではVFAT32を中心に書く。

ディレクトリエントリ

 Windows 95では、それまでのMS-DOSのFAT FSとの互換を取りつつ、 拡張したVFATが使われている。そのため、ディレクトリエントリの予約領域の一部が、 作成時刻やアクセス日付の情報保存に割り当てられたが、 残された2Byte分がFAT32の実装に使われた。

ディレクトリエントリ
00 08 0B 0C 0D 0E
ファイル名(左詰め、余りは20h) 拡張子 ファイル
属性
大小文字
フラグ
(VFAT) 作成時刻
(VFAT)
10 12 14 16 18 1A 1C
作成日付
(VFAT)
アクセス日付
(VFAT)
クラスタ番号
上位2Byte
更新時刻 更新日付 クラスタ番号
下位2Byte
ファイルサイズ

サブディレクトリエントリ (VFAT)
00 01 0B 0C 0D 0E
ID Unicode ファイル名1 0Fh固定 00h固定 ショートネームの
チェックサム
Unicode
ファイル名2
10 1A 1C
Unicode ファイル名2(続き) 0000h固定 Unicode
ファイル名3

ファイル名(エイリアス名)、拡張子
ショートネーム(8.3形式)が保存される領域。8文字、3文字にそれぞれ満たない場合は、 0x20で埋められる。先頭バイトが0xE5のときは削除されたファイルを意味し、 先頭バイトが0x01のとき、先頭バイトが0xE5であることを示す。 ボリュームラベルの場合は、ファイル名、拡張子合わせて11Byteで記録する。
作成時刻、作成日付、アクセス日付
従来のFATでは予約領域だった。バイナリフォーマットは従来と同じ。
更新時刻
更新された時刻を示す。ビットフィールドは以下の通り。
HHHHHmmm mmmsssss
hhhhh 時(0〜23)
mmmmmm 分(0〜59)
ssss 秒(0〜29 実際には2倍する)
更新時刻
更新された日付を示す。ビットフィールドは以下の通り。
YYYYYYYM MMMDDDDD
YYYYYYY 年(0〜99 1980年から)
MMMM 月(1〜12)
DDDDD 日(1〜31)
ファイル属性
属性値は、
0x01 読み込み専用
0x02 隠しファイル
0x04 システムファイル
0x08 ボリュームラベル
0x10 ディレクトリ
0x20 通常のファイル
大小文字フラグ
Windows NTで使用(多分POSIXのファイルネームに合わせるため)。
クラスタ番号上位2Byte
ここが使われず残されていたのは、FAT32への布石だったのか?
ID
bit0-5 サブエントリ番号(1から)
bit 6 0bで途中のサブエントリ、1bで最後のサブエントリ
作成時刻、作成日付、アクセス日付
従来のFATでは予約領域だった。

FAT32の最大容量

 よくわからんが、最大2TB/パーティション。

クラスタサイズ

 FAT32では、デフォルトで4KBytesに設定され、 1TByte以下までは4KByteのままでよい。

ディレクトリエントリの増加

 FAT16のディレクトリエントリは、最大でも64K個程度であるが、FAT32だと512K個程度となり、 ディスクアクセスの低下を招く。そのため、以下のような仕組みが追加されている。

空き容量の再計算の抑止

 FAT16までは、ディスクの空き容量を算出するには、FATを全て読み出し、 未使用のエントリを数えなくてはならなかった。これを避けるために、 FAT32では予約セクタ内にFSINFOという領域を追加し、そこに未使用のクラスタ数が書き込まれている。 (空き容量算出は早くなるけど、 ファイルを追加するたびにFSINFOを書き換えなきゃならんので遅くなる気もするけど、 遅延書き込みでもやってるんでしょう)。

 FSINFOは論理セクタ番号1(セクタ番号は0から始まる)のオフセット1E4hから始まり、 下図のような構造を持つ。空きクラスタ数が-1(FFFFFFFFh)なら、値が計算されていないことを示す。 もちろん、FSINFOの示す空きクラスタ数と実際のクラスタ数は一致していなければならないが、 システムの障害等で差異がある場合は、Scandisk等で整合を取る。

FSINFOのイメージ
0000 52 52 61 41 00 00 00 00 00 00 00 00 00 00 55 AA
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
......
bfFSinf_Sig 空きクラスタ数 最終書き込み
クラスタ番号
01E0 00 00 00 00 72 72 41 61 FF FF FF FF 02 00 00 00
01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA

FSINFOBIGFATBOOTFSINFO)の構造
オフセット フィールド名 サイズ(Byte) 内容
00h bfFSinf_Sig 4 0x61417272L "rrAs"固定
04h bfFSinf_free_clus_cnt 4 空きクラスタ数
08h bfFSinf_next_free_clus 4 最終書きこみクラスタ番号
0Ch bfFSinf_resvd 12 予約領域

最終書き込みクラスタ番号の利用

 MS-DOS 3.xから、DPBには最終書き込みクラスタ番号が保存されており、 最後に書き込んだクラスタ以降にデータを書き込むことができる。 なので、デフラグメンテーションが適切に実行されていれば、フラグメントを抑制させる効果がある。 また、最後の書き込んだクラスタよりFATを検索することにより、ディスクアクセスを局所化し、 キャッシュを有効利用する効果もある。

 FAT32からはFINFOにも最終書き込みクラスタ番号が保存され、起動直後でもこの値を利用できる。 また、この値はディスクリセット(ファンクション0Dh)の影響を受けない。