mirror of
https://github.com/Tolik-Trek/FORMAT.git
synced 2026-06-15 01:11:39 +03:00
144 lines
11 KiB
Markdown
144 lines
11 KiB
Markdown
Вот подробный алгоритм и формулы для программы низкоуровневого форматирования в 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
|
||
|
||
1. Выбор FAT (Пороговые значения)
|
||
|
||
FAT12: До 4084 кластеров в области данных. (Макс. объем зависит от размера кластера, но обычно до ~32 МБ).
|
||
FAT16: От 4085 до 65524 кластеров. (Обычно от ~32 МБ до ~2 ГБ с 32-килобайтными кластерами. Теоретически до 4 ГБ с 64К кластерами, но не поддерживается многими ОС).
|
||
FAT32: От 65525 кластеров и более. (От ~512 МБ до 2 ТБ. Официально до 32 ГБ в Windows, но работает и больше).
|
||
Важно: Это кластеры, а не байты!
|
||
|
||
2. Ключевые вычисляемые параметры
|
||
|
||
Общие переменные:
|
||
|
||
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
|