11 KiB
Вот подробный алгоритм и формулы для программы низкоуровневого форматирования в FAT. Это не просто вызов стандартных утилит, а именно создание структуры разделов "с нуля".
Общий порядок действий (Алгоритм)
Определение параметров носителя и выбор FAT:
Получить общий размер диска/раздела в секторах (total_sectors). Получить размер сектора (обычно 512, 1024, 2048, 4096 байт). bytes_per_sector. Ключевое решение: На основе total_sectors * bytes_per_sector выбрать тип FAT (12/16/32). Используй пороговые значения (см. ниже). Вычисление основных геометрических параметров:
Рассчитать sectors_per_cluster. Это степень двойки (1, 2, 4, 8, ... 64). Зависит от размера тома. Определить размер зарезервированной области (reserved_sectors), обычно 1 для дисков, больше для разделов. Для FAT32 минимум 32. Определить количество копий FAT (num_fats). Обычно 2. Рассчитать размер одной таблицы FAT (sectors_per_fat). Самый сложный расчет, зависит от всего. Создание загрузочной записи (BPB - Bios Parameter Block):
Заполнить структуру BPB (для FAT12/16) или BPB32 (для FAT32) вычисленными значениями. Для FAT32 дополнительно вычислить и заполнить структуру FSInfo. Запись структур на диск:
Сектор 0: Записать MBR с таблицей разделов (если форматируем весь диск, а не раздел). Первый сектор раздела (Logical Sector 0):
Записать BPB (и возможно, загрузочный код). Для FAT32: записать FSInfo (обычно в сектор 1) и Backup Boot Sector (обычно в сектор 6). Зарезервированная область: Пропустить reserved_sectors. Таблицы FAT: Записать num_fats копий FAT, каждая размером sectors_per_fat.
Инициализировать первые кластеры:
FAT[0] = 0xF?? | media_type (например, 0xF8 для HDD). FAT[1] = 0xFFF / 0xFFFF / 0x0FFFFFFF (конец цепочки). Область данных: Заполнить корневой каталог (для FAT12/16) нулями. Для FAT32 корневой каталог находится в кластере 2. Формулы и детали для каждой FAT
- Выбор FAT (Пороговые значения)
FAT12: До 4084 кластеров в области данных. (Макс. объем зависит от размера кластера, но обычно до ~32 МБ). FAT16: От 4085 до 65524 кластеров. (Обычно от ~32 МБ до ~2 ГБ с 32-килобайтными кластерами. Теоретически до 4 ГБ с 64К кластерами, но не поддерживается многими ОС). FAT32: От 65525 кластеров и более. (От ~512 МБ до 2 ТБ. Официально до 32 ГБ в Windows, но работает и больше). Важно: Это кластеры, а не байты!
- Ключевые вычисляемые параметры
Общие переменные:
total_sectors - общее число секторов раздела. bytes_per_sector - 512, 1024, 2048, 4096. sectors_per_cluster (spc) - степень двойки. Подбирается для оптимального количества кластеров. reserved_sectors (rsvd_sec_cnt) - обычно 1 (FAT12/16) или 32 (FAT32). num_fats - почти всегда 2. root_dir_entries (root_ent_cnt) - только для FAT12/16. Обычно 512 (для дискет 224). Для FAT32 = 0. sectors_per_fat (fat_sz32 для FAT32) - самый важный и сложный параметр. Алгоритм расчета sectors_per_fat (итеративный или прямой)
Для FAT12/16:
Рассчитать размер корневого каталога в секторах: root_dir_sectors = ((root_dir_entries * 32) + (bytes_per_sector - 1)) / bytes_per_sector Рассчитать размер области данных в секторах: data_sectors = total_sectors - (reserved_sectors + (num_fats * fat_sz) + root_dir_sectors) Здесь fat_sz (искомое) пока неизвестно. Рассчитать общее число кластеров: total_clusters = data_sectors / sectors_per_cluster Теперь можно найти нужный размер FAT:
Для FAT16: Каждая запись FAT - 2 байта. fat_sz = (total_clusters * 2 + (bytes_per_sector - 1)) / bytes_per_sector Для FAT12: Каждая запись - 1.5 байта. fat_sz = (total_clusters * 3 + 1) / (2 * bytes_per_sector) (с округлением вверх). Но fat_sz влияет на data_sectors. Это цикл. На практике используют итерацию или таблицы. Простой способ:
Сначала грубо оцени data_sectors = total_sectors - reserved_sectors - root_dir_sectors. Посчитай total_clusters, затем fat_sz. Уточни data_sectors, вычтя num_fats * fat_sz. Пересчитай total_clusters. Если изменился сильно - повтори. Для FAT32:
Формула проще, т.к. корневой каталог в области данных. data_sectors = total_sectors - reserved_sectors - (num_fats * fat_sz32) total_clusters = data_sectors / sectors_per_cluster Размер записи FAT32 - 4 байта. Поэтому: fat_sz32 = (total_clusters * 4 + (bytes_per_sector - 1)) / bytes_per_sector Опять цикл. Стартовое приближение: fat_sz32 = 0. Повторять расчет, пока fat_sz32 не стабилизируется (обычно 2-3 итерации). Структуры данных (Упрощенно)
Общая структура BPB (смещения для сектора 512 байт): 0x00: JMP инструкция (3 байта) 0x03: OEM Name (8 байт) 0x0B: bytes_per_sector (WORD) 0x0D: sectors_per_cluster (BYTE) 0x0E: reserved_sectors (WORD) 0x10: num_fats (BYTE) 0x11: root_ent_cnt (WORD) ; 0 для FAT32 0x13: total_sectors_16 (WORD) ; если 0, см. 0x20 0x15: media (BYTE) ; 0xF8 для HDD 0x16: fat_sz_16 (WORD) ; 0 для FAT32 0x18: sectors_per_track (WORD) 0x1A: num_heads (WORD) 0x1C: hidden_sectors (DWORD) ; важно для разделов 0x20: total_sectors_32 (DWORD)
Дополнение для FAT12/16 (Extended BPB): 0x24: drive_number (BYTE) 0x25: reserved (BYTE) 0x26: boot_sig (BYTE) ; 0x29 0x27: volume_id (DWORD) 0x2B: volume_label (11 BYTE) 0x36: file_system_type (8 BYTE) ; "FAT12 ", "FAT16 " 0x3E: boot_code (448 BYTE) 0x1FE: signature (WORD) ; 0xAA55
Дополнение для FAT32 (Extended BPB): 0x24: fat_sz_32 (DWORD) ; sectors_per_fat 0x28: ext_flags (WORD) 0x2A: fs_version (WORD) ; 0 0x2C: root_cluster (DWORD) ; обычно 2 0x30: fs_info_sector (WORD) ; обычно 1 0x32: backup_boot_sector (WORD) ; обычно 6 0x34: reserved[12] (12 BYTE) ... (поля drive_number, boot_sig, volume_id, label, type аналогичны, но смещения другие) 0x1FE: signature (WORD) ; 0xAA55
Порядок записи для FAT32 (особое внимание!) Сектор 0: Основная загрузочная запись (BPB32). Сектор 1: Структура FSInfo (опционально, но рекомендуется). Сектор 6: Резервная копия загрузочного сектора (Backup Boot Sector). Должна быть идентична сектору 0. Сектор 7 и далее: Зарезервированная область. FAT1: Начинается с сектора reserved_sectors (обычно 32). FAT2: Начинается с сектора reserved_sectors + fat_sz32. Область данных: Начинается с сектора reserved_sectors + num_fats * fat_sz32.
Кластер 2: Является началом корневого каталога (значение root_cluster в BPB). На что обратить особое внимание
Выравнивание: Для производительности на современных SSD резервируй reserved_sectors так, чтобы FAT и данные начинались с границ больших блоков (например, 1 МБ). Размер кластера: Большой кластер уменьшает размер FAT и ускоряет работу с большими файлами, но ведет к потере места на мелких файлах. Выбирай по таблицам Microsoft. FAT32 и большие диски: При размерах >32 ГБ многие ОС (старые Windows) откажутся монтировать том. Это ограничение на уровне ОС, а не файловой системы. hidden_sectors: Критически важный параметр при форматировании раздела, а не всего диска. Это смещение раздела от начала диска в секторах. Если установить неверно, диск не загрузится или данные будут потеряны. Зеркалирование FAT: В FAT32 есть флаг ext_flags, который может отключать зеркалирование FAT (копию). По умолчанию зеркалирование включено, и FAT1 и FAT2 должны быть идентичны. Тестирование: Всегда тестируй алгоритм на виртуальных дисках (файлах-образах) перед работой с реальными носителями. Используй hexdump или дисковые редакторы для проверки структур. Рекомендация: Изучи исходный код утилит mkfs.fat (из пакета dosfstools в Linux) или fatformat. Там реализованы все эти алгоритмы с учетом множества крайних случаев.
Продолжить с DeepSeek