Cấu trúc và Triển khai Hệ thống Tệp FAT12

Tổng quan

Bài viết giới thiệu cấu trúc dữ liệu hệ thống tệp FAT12, trình bày các vấn đề phát sinh trong quá trình học tập và lập trình, đồng thời cung cấp ba chức năng chính:

  1. Hiển thị cấu trúc phân vùng khởi động
  2. Hiển thị thông tin thư mục gốc
  3. Đọc nội dung tệp từ khu vực dữ liệu thông qua bảng FAT

Cấu trúc hệ thống tệp FAT12 gồm 5 phân vùng chính. Phân vùng khởi động lưu trữ thông tin cơ bản của hệ thống. Hai bảng FAT1 và FAT2 hoàn toàn giống nhau, tạo thành cơ chế dự phòng. Thư mục gốc chứa danh sách các tệp với thông tin như tên tệp, số cụm, thuộc tính, thời gian... Khu vực dữ liệu lưu trữ nội dung chính của tệp.

STT Vị trí Sector Số Sector Ghi chú
01 0 1 Phân vùng khởi động
02 1 9 Bảng FAT1
03 10 9 Bảng FAT2
04 19 14 Thư mục gốc
05 33 2847 Khu vực dữ liệu

Cấu trúc phân vùng khởi động

Tham số Địa chỉ Loại Kích thước Giá trị mặc định Mô tả
BS_JmpBoot 0 db 3 - Lệnh nhảy
BS_OEMName 3 db 8 FREEDOS Chuỗi OEM (8 ký tự)
BPB_BytePerSec 11 dw 2 0x200 Bytes/sector
BPB_SecPerClus 12 db 1 1 Sector/clusters
BPB_RsvdSecCnt 14 dw 2 1 Sector dành riêng
BPB_NumFATs 16 db 1 2 Số bảng FAT
BPB_RootEntCnt 17 dw 2 0xE0 Số mục thư mục gốc
BPB_TotSec16 19 dw 2 0xB40 Tổng sector (16-bit)
BPB_Media 21 db 1 0xF0 Mã vật lý
BPB_FATSz16 22 dw 2 9 Kích thước bảng FAT
BPB_SecPerTrk 24 dw 2 0x12 Sector/vòng tròn
BPB_NumHeads 26 dw 2 2 Số đầu đọc
BPB_HiddSec 28 dd 4 0 Sector ẩn
BPB_TotSec32 32 dd 4 0 Tổng sector (32-bit)
BS_DrvNum 36 db 1 0 Số ổ đĩa
BS_Reserved1 37 db 1 0 Dự phòng
BS_Bootsig 38 db 1 0x29 Chữ ký khởi động
BS_VolID 39 dd 4 0 Mã thể tích
BS_VolLab 43 db 11 - Tên thể tích
BS_FileSysType 54 db 8 FAT12 Loại hệ thống tệp
BOOT_Code 62 db 448 0x00 Mã khởi động
END 510 db 2 0x55, 0xAA Chữ ký kết thúc

Cấu trúc bảng FAT

Trạng thái Giá trị Mô tả
0 BPB_Media Mã vật lý
1 FFFh Cụm đầu tiên đã dùng
2 ~ N 000h Cụm trống
002h~FEFh Cụm đã dùng
FF0h~FF6h Cụm dành riêng
FF7h Cụm lỗi
FF8h~FFFh Cụm cuối cùng

Thư mục gốc

Tên trường Địa chỉ Kích thước Mô tả
DIR_Name 0x00 11 Tên tệp (8B) + phần mở rộng (3B)
DIR_Attr 0x0B 1 Thuộc tính tệp
DIR_Reserved 0x0C 10 Dữ liệu dự phòng
DIR_WrtTime 0x16 2 Thời gian sửa đổi
DIR_WrtDate 0x18 2 Ngày sửa đổi
DIR_FstClus 0x1A 2 Số cụm bắt đầu
DIR_FileSize 0x1C 4 Kích thước tệp

Lưu ý lập trình

  • Căn chỉnh theo byte:
#pragma pack(push)
#pragma pack(1)
struct CấuTrúc
#pragma pack(pop)
  • Hiển thị chuỗi 11 byte:
printf("DIR_Name: %11.11s\n", re.DIR_Name);
  • Xử lý bảng FAT:
  1. Bảng FAT bắt đầu từ cụm thứ hai, kích thước xác định bởi BPB_FATSz16
  2. Mỗi mục FAT chiếm 12 bit (1.5 byte). Quy trình chuyển đổi:
// Lấy 2 byte đầu
value1 = (fat[i+1] & 0xF) << 8 | fat[i];
// Lấy 2 byte sau
value2 = (fat[i+1] >> 4) | (fat[i+2] << 4);
  1. Quan hệ giữa FAT và dữ liệu:
unsigned short* cluster_list = malloc(...);
readfat(..., cluster_list);

Chuẩn bị file data.img

  1. Tạo đĩa hình ảnh:
dd if=/dev/zero of=data.img bs=512 count=2880
mkfs.fat -F 12 data.img
  1. Gắn kết và sao chép tệp:
mount -o loop data.img /mnt
cp tệp.txt /mnt/
umount /mnt

Triển khai đọc MBR

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    unsigned char BS_JmpBoot[3];
    char BS_OEMName[9];
    unsigned short BPB_BytePerSec;
    unsigned char BPB_SecPerClus;
    unsigned short BPB_RsvdSecCnt;
    unsigned char BPB_NumFATs;
    unsigned short BPB_RootEntCnt;
    unsigned short BPB_TotSec16;
    unsigned char BPB_Media;
    unsigned short BPB_FATSz16;
    unsigned short BPB_SecPerTrk;
    unsigned short BPB_NumHeads;
    unsigned int BPB_HiddSec;
    unsigned int BPB_TotSec32;
    unsigned char BS_DrvNum;
    unsigned char BS_Reserved1;
    unsigned char BS_Bootsig;
    unsigned char BS_VolID[4];
    char BS_VolLab[12];
    char BS_FileSysType[9];
    unsigned char BOOT_Code[448];
    unsigned short MBR_Flag;
} __attribute__((packed)) MBRInfo;

void inThongTinMBR(const char* path) {
    FILE* fp = fopen(path, "rb");
    MBRInfo mbr;
    fread(&mbr, sizeof(MBRInfo), 1, fp);
    
    mbr.BS_OEMName[7] = '\0';
    mbr.BS_VolLab[10] = '\0';
    mbr.BS_FileSysType[7] = '\0';
    
    printf("OEM Name: %s\n", mbr.BS_OEMName);
    printf("Bytes/Sector: %d\n", mbr.BPB_BytePerSec);
    // ... In các trường khác ...
    printf("Chữ ký khởi động: 0x%x\n", mbr.MBR_Flag);
    
    fclose(fp);
}

Triển khai đọc thư mục gốc

typedef struct {
    char DIR_Name[11];
    unsigned char DIR_Attr;
    unsigned char DIR_Reserved[10];
    unsigned short DIR_WrtTime;
    unsigned short DIR_WrtDate;
    unsigned short DIR_FstClus;
    unsigned int DIR_FileSize;
} __attribute__((packed)) RootEntry;

void inThongTinThuMucGoc(MBRInfo mbr, const char* path) {
    FILE* fp = fopen(path, "rb");
    RootEntry entry;
    
    for(int i=0; i < mbr.BPB_RootEntCnt; i++) {
        fseek(fp, 19*mbr.BPB_BytePerSec + i*sizeof(RootEntry), SEEK_SET);
        fread(&entry, sizeof(RootEntry), 1, fp);
        
        if(entry.DIR_FstClus == 0 || entry.DIR_Name[0] == 0)
            continue;
            
        printf("Tên tệp: %11.11s\n", entry.DIR_Name);
        // ... In thông tin khác ...
    }
    
    fclose(fp);
}

Triển khai đọc nội dung tệp

void docNoiDungTep(MBRInfo mbr, const char* path, const char* tenTep) {
    RootEntry entry;
    if(!timTep(mbr, path, tenTep, &entry))
        return;
        
    unsigned int size = mbr.BPB_BytePerSec * mbr.BPB_SecPerClus;
    char* buffer = malloc(size);
    
    unsigned short currentCluster = entry.DIR_FstClus;
    while(currentCluster < 0xFF8) {
        int offset = 33 * mbr.BPB_BytePerSec + (currentCluster - 2) * size;
        fseek(fp, offset, SEEK_SET);
        fread(buffer, size, 1, fp);
        printf("%s", buffer);
        
        currentCluster = layGiaTriFAT(mbr, currentCluster);
    }
    
    free(buffer);
}

Kết luận

Hệ thống tệp FAT12 minh họa rõ ràng cách thiết kế cấu trúc dữ liệu hiệu quả. Việc hiểu và triển khai các hệ thống như vậy đòi hỏi không chỉ kiến thức lập trình mà còn khả năng tư duy thiết kế hệ thống. Những kỹ thuật như căn chỉnh bộ nhớ, tối ưu lưu trữ, và xử lý dữ liệu phi chuẩn là những bài học quý giá cho việc phát triển phần mềm hệ thống.

Thẻ: hệ thống tệp FAT12 lập trình hệ điều hành đọc ghi đĩa Cấu trúc dữ liệu

Đăng vào ngày 23 tháng 6 lúc 07:38