Размер таблицы размещения файлов FAT32 на диске, отформатированном в Windows 7, не соответствует спецификации FAT32

Я пишу встроенный драйвер FAT32. У меня есть проблемы.

Заполняю свой Kingston DTR30G2 до 1GB нулями и подключаю к боксу с Windows 7, и форматирую в FAT32. Затем на моем компьютере с Linux я выгружаю 1 ГБ флэш-памяти в файл, открываю его в шестнадцатеричном редакторе и получаю следующие значения:

uint16_t BPB_ResvdSecCnt = 32 at offset 0xE
uint8_t BPB_SecPerClus = 8 at offset 0xD
uint8_t BPB_NumFATs = 2 at offset 0x10

Далее я смотрю на общее количество секторов в идентификаторе тома FAT32:

uint32_t DskSize = 30734336 at offset 0x20

Это то же самое, что сообщает Linux:

thinkpad :: ~ % cat /sys/block/sdb/sdb1/size                                      
30734336

Все это соответствует спецификации FAT32. Теперь давайте посмотрим на размер сектора таблицы FAT на диске со смещением 0x24. Это 29951 секторов. Это не соответствует спецификации FAT32. Официальные документы Microsoft объявляют следующее уравнение:

RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec;
TmpVal1 = DskSize – (BPB_ResvdSecCnt + RootDirSectors);
TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
TmpVal2 = TmpVal2 / 2;
FATSz = (TMPVal1 + (TmpVal2 – 1)) / TmpVal2;

Где RootDirSectors постоянно 0 для FAT32, как указано в документах FAT32:

Обратите внимание, что в томе FAT32 значение BPB_RootEntCnt всегда равно 0, поэтому RootDirSectors тома FAT32 всегда равно 0.

Итак, это дает:

TmpVal1 = DskSize – BPB_ResvdSecCnt;
TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
TmpVal2 = TmpVal2 / 2;
FATSz = (TMPVal1 + (TmpVal2 – 1)) / TmpVal2;

Теперь я реализовал это:

int main(void) {

  uint32_t DskSize = 30734336;
  uint32_t FATSz;
  uint16_t BPB_ResvdSecCnt = 32;
  uint8_t BPB_SecPerClus = 8;
  uint8_t BPB_NumFATs = 2;
  uint32_t RootDirSectors = 0;

  uint32_t TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors);
  uint32_t TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
  TmpVal2 = TmpVal2 / 2;
  FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;

  printf("%d\n", FATSz);

}

Этот фрагмент кода дает 29985 секторов в качестве размера FAT.

РЕДАКТИРОВАТЬ:

mkfs.fat 3.0.28 в Linux при использовании со следующими настройками:

mkfs.fat /dev/sdb1 -S 512 -s 8 -F 32 

Дает размер таблицы FAT 29956. Теперь у меня есть три разных номера одной и той же файловой системы на одном разделе.

  • Спецификация FAT32: 29985
  • Windows 7: 29951
  • mkfs.fat: 29956

Кому мне теперь доверять? спецификация или реализация. Почему цифры отличаются на 34 секторов?


person Gala    schedule 10.08.2016    source источник


Ответы (1)


Я нашел копию спецификации, о которой вы, кажется, спрашиваете здесь (PDF) .

Часть документа, на которую вы ссылаетесь (вверху страницы 21), является рекомендательной, а не обязательной — в ней описывается, что сделала некоторая неуказанная версия Windows для расчета размера FAT при форматировании FAT32. объем. Единственное фактическое требование состоит в том, чтобы FATSz был достаточно большим, чтобы вместить FAT. Документ явно разрешает использование FATSz, слишком большого для FAT, и требует, чтобы неиспользуемые сектора обнулялись во время форматирования и игнорировались в противном случае.

Судя по вашим наблюдениям, в современных версиях Windows используется несколько более эффективный алгоритм. (Также может показаться, что связанный документ был неверным, утверждая, что алгоритм, который он описывает, никогда не приводит к более чем 8 потерянным секторам. Я не пытался делать математику, но, возможно, это связано с тем, что объем, который вы , использует кластеры 4 КБ вместо кластеров 8 КБ, указанных в документе для диска 14 ГБ — см. таблицу на стр. 20.)

Если вы форматируете диск, вам нужно либо использовать описанный алгоритм, либо очень тщательно написать свой собственный алгоритм, гарантируя, что он никогда не приведет к слишком маленькому результату. (Или, если так получилось, что вы уже знаете, какого размера будет диск, вы могли бы использовать параметры, которые использует Windows при форматировании диска того же размера.)

Если вы монтируете уже отформатированный диск, вы, конечно, используете значение, хранящееся на диске.

person Harry Johnston    schedule 10.08.2016
comment
Между прочим, если я что-то не упускаю из виду, должно быть несложно реализовать очень простой алгоритм, который всегда дает оптимальный ответ: начните с того, что притворитесь, что вам нужно поддерживать столько кластеров, сколько поместится на весь диск, и вычислите FAT. размер для этого. Это дает вам максимум. Затем уменьшите этот размер на один сектор, подсчитайте, сколько фактических кластеров поместится на диск на этой основе, и посмотрите, поместится ли он по-прежнему. Промыть и повторить. Это звучит неэффективно, но на самом деле это не займет много времени, и это не значит, что вы часто форматируете диски. - person Harry Johnston; 11.08.2016
comment
Мне действительно не нравится, что спецификация FAT32 расплывчата. - person Gala; 11.08.2016