FAT(File Allocation Table)이라는 용어는 이름 그대로 파일의 할당 정보를 표현한 테이블이다. FAT는 구조가 간단하다는 장점 때문에 일반 시스템 외에도 메모리 카드, 디지털 카메라, 플래시 메모리 등에 널리 사용되고 있다.
FAT 파일 시스템은 크게 FAT12, FAT16, FAT32로 나눌 수 있다. FAT 뒤의 숫자는 비트 수로 최대 표현 가능한 클러스트의 수를 의미한다.
FAT형식 | 최대 표현 가능한 클러스트 수 |
---|---|
FAT12 | 4,084 (2^12 - 12) |
FAT16 | 65,524 (2^16 - 12) |
FAT32 | 268,435,444 (2^28) |
FAT12는 12비트를 사용하여 클러스터를 표현할 수 있기 때문에 최대 4,096(2^12)개의 클러스터를 표현할 수 있다. 하지만 000h, 001h, FF6h~FFFh 값은 사용하지 않거나 다른 목적으로예약되어 있기 때문에 최대 4,084(^12 – 12)개의 클러스터를 표현할 수 있다. FAT16의 경우에도 예약된 클러스터를 제외하면 최대 65,524(2^16 – 12) 개의 클러스터를 표현할 수 있다.
FAT32는 268,435,444(2^28 – 12)개의 클러스터를 표현할 수 있다. FAT32에서 28비트만 사용하는 이유는 4비트가 사전에 예약되어 다른 용도로 사용되기 때문이다.
이러한 변천과정은 당연히 저장매체의 용량이 기하급수적으로 커져가면서 파일시스템이 그 용량을 표현하지 못했기 때문에 비트 수를 증가시킨 것이다. 하지만 이러한 비트 수 증가에도 FAT32는 최대 2TB 의 용량까지만 표현가능하다.
현대에는 2TB만 사용하기에는 무리이다. 그래서 FAT32를 확장한 exFAT가 제안되었다. exFAT는 클러스터 표현 비트를 64비트로 확장시켰으며, 비트맵을 사용하여 클러스터를 효율적으로 관리한다. 이외에도 FAT32에서 제한되었던 많은 기능이 추가되었다.
FAT 파일시스템은 크게 예약된 영역(Reserved Area), FAT 영역(FAT Area), 데이터 영역(Data Area)로 나눌 수 있다.
예약된 영역(Reserved Area)는 FAT 파일시스템에서 가장 앞 부분에 위치하는 구조로서 여러 개의 섹터로 구성된다. 예약된 영역의 크기는 기본적으로 FAT12, FAT16에서는 1섹터, FAT32에서는 32섹터를 사용한다.
예약된 영역은 다시 부트 섹터(Boot Sector), FSINFO(File System INFOrmation) 섹터, 추가적인 섹터로 구분된다.
부트 섹터의 크기는 1섹터로 FAT 파일시스템의 처음에 위치한다. 부트섹터(512 bytes)의 구조는 다음과 같다.
부트 섹터의 처음 3 bytes는 0x003E 또는 0x005A의 부트 코드로 점프하기 위한 점프 명령어가 위치한다. 이후 클러스터 크기, FAT 크기, 루트 디렉터리 위치, 총 섹터 수 등의 파일시스템 정보를 기록한 BPB 영역이 온다. 이후에는 파일시스템을 부팅하기 위한 부트 코드가 위치한다.
부트 코드는 점프 명령에 의해 실행되는데, 이 때 BPB 정보를 참조하여 파일시스템을 부팅한다. 부트 코드 실행과정에서 정상적이지 않은 동작이 발생할 경우 에러 메시지를 출력하게 된다.
[ FAT12/16/32 ] 공통된 데이터 구조
[ FAT12/16 ] 추가적인 데이터 구조
[ FAT32 ] 추가적인 데이터 구조
FAT32의 경우 부트 섹터가 손상될 경우를 대비해서 6번째 섹터에 내용을 백업해 둔다. 따라서 부트 섹터가 정상적이지 않을 경우 백업되어 있는 부트 섹터를 복사하여 복구할 수 있다.
FSINFO는 일반적으로 1번째 섹터(부트 섹터 다음)에 저장되는 구조로 7번째 섹터에 내용을 백업해 둔다. FSINFO 구조의 용도는 운영체제에게 첫 비할당 클러스트의 위치와 전체 비할당 클러스트의 수를 할려준다.
이는 우선 첫번째 비할당 클러스트의 위치를 알려줌으로서 해당 볼륨에 저장하고자 하는 파일을 빠르게 할당할 수 있도록 도와준다. 그리고 전체 비할당 클러스트의 수를 통해 해당 파일이 볼륨에 할당 가능한지 여부도 알 수 있다. 특정 볼륨에 파일을 복사할 경우 여유 공간이 있는지 파악하기 위해서 기존에는 FAT 영역 전체를 검색해봐야 했다. 하지만 FSINFO 구조 덕분에 볼륨에 여유 공간을 빠르게 파악할 수 있다.
다음은 FSINFO섹터의 데이터 구조이다.
부트 섹터는 0,6번 섹터를 사용하고, FSINFO는 1,7번 섹터를 사용하고 있다. 이외에도 2번 섹터는 부트 섹터의 부트 코드 영역이 부족할 경우 추가적으로 사용할 수 있는 섹터이다. 그리고 이 내용은 8번에 백업해 둔다. 이렇게 기본적으로 FAT32는 0, 1, 2, 6, 7, 8번의 섹터를 사용한다.
결과적으로 32섹터 중에서 6개 섹터만 사용하고 나머지 섹터는 만약을 대비해 예약되어 잇다. 따라서 이러한 섹터는 일반적으로 어플리케이션에서 접근하지 않기 때문에 간혹 예약된 나머지 영역에 데이터를 숨겨두는 경우가 있다.
FAT(File Allocation Table) 영역은 예약된 영역 바로 다음에 오는 파일 할당 테이블이다. 쉽게 말해 데이터 영역에 저장된 파일들의 할당 관계를 표시해주는 테이블이다.
FAT영역은 다시 두 개로 나눠지는데 두 번째 영역은 첫 번째 영역이 손실되었을경우를 대비한 백업본이다. 따라서 두 영역은 동일한 값이 저장되게 된다.
FAT 영역의 목적은 데이터 영역에 저장된 파일의 클러스트 할당 관계를 테이블 형태로 보여주는 것이다. FAT12, FAT16은 2 bytes, FAT32는 4 bytes를 통해 데이터 영역의 시작 클러스터부터 마지막 클러스터까지 할당 관계를 표시한다. 클러스터가 만약 4KB 크기를 가진다고 하면, FAT32에서는 각 클러스터가 FAT 영역의 4 bytes에 대응된다는 것이다.
FAT32에서 4 bytes씩 클러스터를 표현하므로 각 섹터(512 bytes)에는 128개의 클러스터를 표현할 수 있다. 만약 FAT 영역이 100개의 섹터 크기를 가지고, 클러스터 크기가 4KB라면 데이터 영역의 총 크기는 50MB(128 X 100 X 4096bytes)가 된다.
앞서 살펴본 클러스터에 대응되는 FAT 영역의 각 바이트(2:FAT12/16, 4:FAT32)는 FAT 엔트리라는 용어로 부른다. 각 FAT 엔트리는 데이터 영역의 각 클러스터에 대응된다.
다음은 FAT 영역을 좀 더 자세히 살펴본 것이다.
위의 4 바이트씩 표현된 부분이 FAT32에서 데이터 영역의 각 클러스터를 표현하는 FAT 엔트리이다. 특이한 점은 데이터 영역의 클러스터가 0 부터 시작하는 것이 아닌 2 부터 시작한다는 점이다. 이러한 이유는 FAT 영역의 1,2 FAT 엔트리는 별도의 용도로 예약되어 있는데, 첫 번째 FAT 엔트리는 해당 미디어의 타입을 나타내고, 두 번째 FAT 엔트리는 파티션의 상태를 나타낸다.
FAT 엔트리는 다음과 같은 특별한 값을 가질 수 있다. 표에 나타나지 않은 값은 다음 클러스터의 값을 가르킨다.
다음은 FAT 영역의 첫 섹터를 덤프한 결과이다. 0, 1번째 FAT 엔트리는 예약되어 있으므로 무시하고, 두 번재 엔트리부터 살펴보자. FAT Entry 2의 값이 0x0FFFFFFF 값을 가지므로 해당 클러스터는 파일의 끝을 의미한다. 따라서, 데이터 영역의 첫 클러스터(클러스터 2)를 가지는 파일은 하나의 클러스터를 사용한다. 다시 말해, 클러스터가 4KB라고 했을 때 파일 크기가 4KB보다 작다는 의미이다. FAT Entry 3번 역시 같은 의미이다.
FAT Entry 4번은 0x05 값을 가진다. 즉, FAT Entry 5번을 가르킨다. FAT Entry 5는 다시 0x06 값으로 FAT Entry 6을 가르킨다. 이렇게 따라가보면 FAT Entry 8번이 마지막 엔트리가 된다. 따라서 데이터 영역의 3번째 클러스터부터 할당된 파일은 총 5개의 클러스터를 사용한다. 즉, 16 ~ 20 KB 사이의 크기를 가진다는 의미이다.
결과적으로 FAT 영역은 FAT Entry를 통해 데이터 영역의 클러스터 할당 상태 및 연결 상태를 표현해 준다. 파일의 정확한 크기 및 이름, 확장자, 시간정보 등을 얻고 싶다면 이후에 살펴본 데이터 영역의 디렉터리 엔트리(Directory Entry) 구조를 확인해야 한다.
만약, 파일을 저장 한 후에 삭제하면 해당 파일이 저장된 클러스터에 대응되는 FAT Entry는 모두 0x00으로 초기화된다. 그리고 이후에 살펴본 디렉터리 엔트리에 삭제 플래그를 기록하게 된다. 하지만 데이터가 저장된 데이터 영역의 데이터는 접근하지 않기 때문에 삭제한 파일도 복구할 수 있다.
데이터 영역(Data Area)은 FAT 영역 다음에 오는 영역이다. 데이터 영역에 저장되는 데이터는 크게 파일의 메타 정보(파일 이름, 크기, 타입, 시간 정보, 시작 클러스터 위치 등)을 저장하고 있는 디렉터리 엔트리라는 구조와 실제 파일 데이터로 나눠볼 수 있다.
다음은 데이터 영역을 간단히 나타낸 것이다.
위의 그림은 루트 디렉터리 내부에 서브 디렉터리가 하나인 경우를 가정하여 나타낸 것이다. 루트 디렉터리는 FAT12, FAT16의 경우에 FAT영역에 바로 따라 온다. 하지만 FAT32는 그 위치가 고정되어 있지 않고, 예약된 영역 부트 섹터 내부의 BPB의 값을 통해 그 위치를 나타낸다. 하지만 일반적으로 FAT32도 FAT 영역에 따라 나온다.
루트 디렉터리가 FAT영역 다음의 첫 클러스터에 오지만 FAT 엔트리 0,1번은 예약되어 있기 때문에 첫 클러스터스의 번호는 FAT 영역을 기준으로 했을 때 2번이 된다.
폴더 및 파일의 정보는 디렉터리 엔트리라는 구조를 통해 나타낸다. 각각의 폴더 및 파일은 하나 이상의 디렉터리 엔트리를 통해 표현되며, 그 크기는 32 bytes이다. 다음은 디렉터리 엔트리의 데이터 구조이다.
디렉터리 엔트리는 위의 그림과 같이 이름, 확장자, 속성, 생성 날짜 및 시간, 마지막 접근 시간, 마지막 수정 날짜 및 시간, 시작 클러스터 위치, 논리적 파일 크기 정보를 가지고 있다. 폴더를 표현할 경우 확장자가 없으므로 확장자는 표현하지 않는다. 루트 디렉터리에 위치한 특정 파일이나 폴더에 접근하고자 하는 경우 루트 디렉터리의 디렉터리 엔트리를 검색하면서 해당 파일의 이름을 찾는다.
파일 이름을 가진 디렉터리 엔트리를 찾았다면 시작 클러스터 정보(Starting Cluster Hi + Starting Cluster Low)를 얻어 해당 위치부터 파일 크기 만큼 파일을 획득하면 될 것이다. 하지만 파일은 항상 데이터 영역의 연속된 클러스로 표현되지 않고 조각날 수 있기 때문에 이러한 조각난 파일 정보는 FAT 영역에서 시작 클러스터부터 따라가면서 원하는 클러스터 만큼 획득하면 된다. 파일 크기에 해당하는 클러스터를 획득한 경우에 마지막 클러스터에는 파일 슬랙이 존재할 수 있으므로 정확한 파일 데이터만 얻고자 한다면 파일 크기 만큼만 떼어내면 될 것이다.
하위 디렉터리를 탐색하고자 한다면 파일과 마찬가지로 하위 디렉터리 이름을 가진 디렉터리 엔트리를 얻어, 하위 디렉터리가 위치한 클러스터로 이동하면 될 것이다. 이동하게 되면 다시 그 클러스터에는 하위 디렉터리의 폴더 및 파일의 정보를 담고 있는 32 바이트의 디렉터리 엔트리가 연속적으로 나올 것이다.
우리가 탐색기를 열어 확인하는 파일의 이름, 확장자, 시간 정보 등은 데이터 영역의 실제 파일을 통해 얻어오는 정보가 아니라 디렉터리 엔트리만 탐색하여 얻는 정보이다. 그렇다면 숨긴 파일, 읽기 전용 파일, 시스템 파일 등은 어떻게 구분하는 것일까? 그것은 디렉터리 엔트리의 속성을 통해 가능하다. 다음은 디렉터리 엔트리의 속성(offset 11)에 나올 수 있는 값이다.
값 (Binary) | 설명 |
---|---|
0000 0001 | Read only |
0000 0010 | Hidden file |
0000 0100 | System file |
0000 1000 | Volume label |
0000 1111 | Long file name |
0001 0000 | Directory |
0010 0000 | Archive |
만약에 파일 이름이 8 bytes 보다 길다면 속성에 "0000 1111"을 갖는 긴 파일 이름(Long file name) 엔트리를 추가적으로 사용한다.
이처럼 복잡한 폴더 구조도 루트 디렉터리를 기점으로 탐색해 나가게 되면 쉽게 모든 파일을 탐색할 수 있을 것이다. 탐색하여 원하는 파일을 찾은 경우 해당 파일은 시작 클러스터 위치를 통해 FAT 영역을 확인하여 연결된 파일 데이터를 획득 한 후 슬랙 영역을 제거하면 논리적인 파일을 얻을 수 있다.