Программирование дисковой подсистемы

Тема в разделе "WASM.BEGINNERS", создана пользователем s3dworld, 27 дек 2010.

  1. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    На сколько я понимаю, ни одна FAT (ну точно не FAT12) не поддерживает восстановление данных после сбоев компьютера. Я прав?
     
  2. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Гарантировать себя от сбоев (прерываний) невозможно, поэтому лепят что-то типа транзакций. При начале файловой операции вы "открываете" транзакцию (запоминая что и как будете делать и инфа для rollback). Далее до завершения (успех) операция не считается закрытой. После рестарта (аварийного) ваша система находит незакрытую транзацию и (наверное) откатывает все по дефолту либо предлагает оставить полузаписанное что-то (иногда лучше чего-то чем совсем ничего).

    Про FAT не знаю но знаю что были специальные утилиты восстановления битых файлов что косвенно подтверждает вашу догадку.
     
  3. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Всем доброго вечера!

    Вроде бы завершил придумывать свою файловую систему. Теперь буду писать несколько утилит, для того чтобы можно было создавать образы, форматировать дискеты и бродить по просторам файловой системы. Почитать про мою новую файловую систему Вы сможете по этой ссылке: http://dubrovkin.h18.ru/DFS-FD.htm.

    Жду Ваших комментариев!
     
  4. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Владимир Кулаков: Программирование дисковых подсистем.
    Почти 800 страниц.
    Есть примеры.
    Поищите в сети.
     
  5. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    s3dworld
    А теперь по этой структуре покажи нам хекс дамп ФС с размещением там нескольких файлов, разных размеров. С выделением в хексе, какая порция данных относится к какому файлу.
    Мы посмотрим.
     
  6. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    TermoSINteZ
    Если честно, то не понял о чём Вы. Что значит:
    > С выделением в хексе, какая порция данных относится к какому файлу.
    У меня не может быть так, чтобы в одном кластере лежали данные разных файлов.
     
  7. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    s3dworld
    Тогда покажи как может быть.
    А если файл вмещается в 1 кластер? Тогда что?
    Я о том что вот вы показываете хекс дамп. Выделяете разным цветом последовательности байт и показываете стрелочками "тут лежит имя файла, тут лежит размер, тут смещение, тут сами данные..." и так далее.
     
  8. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Полностью согласен, что моя файловая система очень уж громоздка. Я решил почитать спецификацию по FAT (http://www.gamedev.ru/files/?id=62689). Так же почитал статью: http://www.avprog.narod.ru/progs/fat.html#02h.

    Решил написать для себя подобие FAT. По сути всё очень просто. Но есть несколько моментов, которые хочу чтобы Вы мне уточнили.

    МОМЕНТ 1
    В FAT может быть две области с описанием (характеристиками, цепочками) кластеров. То есть будет ли их две или одна, это по желанию. Корневая папка только одна. И как я понял, никакая папка не дублируется. И данные файлов тоже не дублируются, даже очень важные? То есть я имею в виду, что у нас может быть папка Soft в корневой папке. А в этой папке будет ещё папка Paint. Но может получиться так, что кластеры, где располагаются элементы этой папки, повреждены. И что, тогда мы просто-напросто потеряли не только ветвь развития, но и занятые кластеры? Как это реализуется, чтобы не потерять след. И собственно тоже самое касается файлов, не именно описания файла (то что находится в списке папки), а именно содержимое файла. Дублируется ли оно или как происходит. А то ведь так можно навсегда потерять данные в случае порчи сектора кластера. А если есть дубляж, то можно из дубля взять данные и поправить кластеры оригинала. Только тогда при каждой операции записи, нужно делать двойную работы (на оригинал и на копию). Оправдано ли это и как вообще делается в файловых системах?

    МОМЕНТ 2
    Что касается отключения электричества или других проблем. Думаю что не стоит полностью полагаться на без проблемную работы компьютера, поэтому лучше бы понять как стоит восстанавливать данные. Выше я указал статью про FAT. Там написано как записывать файл, как удалять, перемещать, копировать. Но там ничего не написано про возникающие ситуации (про ошибки). Если рассмотреть удаление, то это нужно пометить элемент в списке папки как удалённый, пройтись по цепочке кластеров, на которые он указывает (точнее на начало кластера цепочки он указывает), и обнулить их. Так с чего начать нужно?

    Если сначала начать обнулять кластера (не сами кластера, а именно описания кластеров) и вдруг в этот момент отключили электричество, то получится классная вещь: файл существует, занимает размер (или не занимает если папка), а кластеры, на которые он указывает содержат 0x00 (точнее описания кластеров). Данные пропали!

    А если сначала помечать объект в списке как удалённый и вдруг отключили питание. Тогда объект из списка мы потеряли, но и потеряли кластеры, так как они в списке кластеров навечно остались занятыми (конечно если не запускать специальную утилиту, которая будет искать для начала цепочки файла указывающий на неё файл). Получается что везде не хорошо. Так как тогда себя обезопасить от такой операции?

    Ведь удаление - это ещё цветочки, хотя и оно подразумевает обширную программу, если удалять папку, в которой есть файлы и папки. Тогда нужно будет проходиться по каждому элементу и очищать его не только из списка, но и из характеристики кластеров. А вдруг при 346 файле из 700 произойдёт отключение питания. Что тогда? Как восстановить?

    Я уже боюсь думать про такие зверские операции, как запись данных в файл (файл увеличивается или уменьшается - одним словом, меняется). Тут у меня даже фантазия не включается как сделать.

    Другое дело переименование - тут просто изменить то, что лежит в секторе. Да, кстати, если сделать что кластер будет не 1 сектор, а больше, то возможна и ошибка в таком случае, что только половина кластера была записана при отключении питания.

    Даже простое перемещение требует как минимум два раза записи (откуда и куда). А если все эти операции делать с учётом копий, то вообще чекануться можно.

    Журналирование, журналирование... а как им реализовать всё это?

    Выделить область для журнала (надеюсь журнал дублировать не нужно будет) и писать там то, что собираешься сделать, и если сделал, то уже отметку затираешь. Но по сути что туда писать? Что писать при переименовании итак понятно, если делать её и для дублирования: какой объект был, какой нужен и далее вносить записи в журнал, переименовали ли в оригинале, переименовали ли в копии. При перемещении что-то наподобие. При удалении чёрт знает что туда вносить. А при записи в файл, у меня вообще мозги отказывают соображать. Не писать же мне в журнале те данные, которые я хочу добавить в файл, с какой позиции и прочее...

    В общем у меня сейчас бурно играет фантазия. Если кто-то может, дайте дельный урок - объясните по пальцам.
     
  9. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Всем доброго утра!

    Хотелось бы у Вас спросить по поводу фрагментации и дефрагментации.

    В моём понимании, фрагментация - это не когда между объектами есть свободное место.

    [​IMG]

    А когда объекты разделены на кластеры, путь к которым проходит через другие кластеры.

    [​IMG]

    Процесс дефрагментации позволяет собрать кластеры объекта в одном месте.

    [​IMG]

    Но мне интересно, как же программа дефрагментации производит эти манипуляции. Как осуществляется дефрагментация в FAT? Про NTFS даже думать не хочу, тем более что сколько не пытался в Windows 7 выполнить дефрагментацию, она оказывалась всегда не нужной. Такое ощущение, что Windows 7 дефрагментацию сам выполняет в фоновом режиме когда ему это нужно.

    Просто дефрагментацию - это перемещение кластеров в другое место, то есть копирование. А для копирования нужно чтобы место свободное уже было. Ведь так придётся уже какой-то кластер копировать в резервный кластер, кластер где он был раньше очищать и на его место копировать данные другого кластера. И при этом нужно переуказывать индексы следующих кластеров в цепочках и переуказывать индексы кластеров начала цепочек в самих записях объектов. Тут уже если произойдёт сбой, будет не поправимое (по крайней мере для FAT, как мне кажется).

    Может кто-нибудь рассказать как производится дефрагментация?
     
  10. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Всем доброго дня!

    Не стал я использовать FAT12, а решил написать своё подобие. Сейчас реализовываю менеджер для работы с образами SFS12. Если кому интересно, то предлагаю содержимое файла с объявлениями структур:

    Код (Text):
    1. #pragma once
    2.  
    3. #include <memory>
    4.  
    5. #define SFS12_BOOT_SECTOR_IDENTIFIER                            "SFS12\0"
    6. #define SFS12_BOOT_SECTOR_SIGNATURE                             0xAA55
    7. #define SFS12_BOOT_SECTOR_SIGNATURE_BYTE1                       0x55
    8. #define SFS12_BOOT_SECTOR_SIGNATURE_BYTE2                       0xAA
    9.  
    10. #define SFS12_CLUSTERS_LIST_FREE                                0x0000
    11. #define SFS12_CLUSTERS_LIST_ERROR                               0x0FF6
    12. #define SFS12_CLUSTERS_LIST_END_CHAIN_BOOT                      0x0FF7
    13. #define SFS12_CLUSTERS_LIST_END_CHAIN_RESERVED                  0x0FF8
    14. #define SFS12_CLUSTERS_LIST_END_CHAIN_CLUSTERS_LIST             0x0FF9
    15. #define SFS12_CLUSTERS_LIST_END_CHAIN_COPY_CLUSTERS_LIST        0x0FFA
    16. #define SFS12_CLUSTERS_LIST_END_CHAIN_ROOT_DIRECTORY            0x0FFB
    17. #define SFS12_CLUSTERS_LIST_END_CHAIN_ROOT_DIRECTORY_ITEMS      0x0FFC
    18. #define SFS12_CLUSTERS_LIST_END_CHAIN_DIRECTORY                 0x0FFD
    19. #define SFS12_CLUSTERS_LIST_END_CHAIN_DIRECTORY_ITEMS           0x0FFE
    20. #define SFS12_CLUSTERS_LIST_END_CHAIN_FILE                      0x0FFF
    21.  
    22. #define SFS12_OBJECT_DESCRIPTION_STATUS_FREE                    0
    23. #define SFS12_OBJECT_DESCRIPTION_STATUS_OBJECT                  1
    24. #define SFS12_OBJECT_DESCRIPTION_INDEX_PARENT_ROOT_DIRECTORY    0
    25.  
    26. #pragma pack(1)
    27. struct SFS12_BootSector
    28. {
    29.     char jmpCode[3];
    30.     char identifier[8];
    31.     char description[12];
    32.     unsigned char cylinders;
    33.     unsigned char tracksInCylinder;
    34.     unsigned char sectorsInTrack;
    35.     unsigned short int bytesInSector;
    36.     unsigned char sectorsInCluster;
    37.     unsigned short int indexReserved;
    38.     unsigned short int indexClusters;
    39.     unsigned short int indexCopyClusters;
    40.     unsigned short int indexRootDirectory;
    41.     unsigned char unfinishedAction;
    42.     char code[472];
    43.     char signature[2];
    44. };
    45. #pragma pack()
    46.  
    47. #pragma pack(1)
    48. struct SFS12_ObjectDescription
    49. {
    50.     unsigned char status;
    51.     unsigned short int indexParent;
    52.     char name[24];
    53.     char expansion[4];
    54.     unsigned char attributes;
    55.     unsigned int size;
    56.     char createDate[4];
    57.     char createTime[4];
    58.     char readDate[4];
    59.     char readTime[4];
    60.     char writeDate[4];
    61.     char writeTime[4];
    62.     unsigned short int indexData;
    63.     unsigned short int items;
    64. };
    65. #pragma pack()
    66.  
    67. union SFS12_Union_UShortToChars
    68. {
    69.     unsigned short int value;
    70.     char bytes[2];
    71. };
    72.  
    73. unsigned int SFS12_GetTextLength(const char* _src);
    74. unsigned int SFS12_GetTextLength(const char* _src,const unsigned int _maxLength);
    75.  
    76. bool SFS12_SetText(char* _dsc,const unsigned int _dscLength,const char* _src);
    77. bool SFS12_SetText(char* _dsc,const unsigned int _dscLength,const char* _src,const unsigned int _srcLength);
    78.  
    79. bool SFS12_SetDate(char* _dsc,const unsigned char _day,const unsigned char _month,const unsigned short int _year);
    80. bool SFS12_SetTime(char* _dsc,const unsigned char _hour,const unsigned char _minute,const unsigned char _second);
    81.  
    82. bool SFS12_ClearCluster(char* _data,const unsigned short int _sectorsInCluster,const unsigned short int _indexCluster);
    83. bool SFS12_ClearClusters(char* _data,const unsigned short int _sectorsInCluster,const unsigned short int _indexCluster,const unsigned short int _clustersCount);
    84.  
    85. bool SFS12_SetCluster(char* _data,const unsigned short int _sectorsInCluster,const unsigned short int _indexCluster,const char* _cluster);
    86. bool SFS12_SetClusters(char* _data,const unsigned short int _sectorsInCluster,const unsigned short int _indexCluster,const unsigned short int _clustersCount,const char* _clusters);
    87.  
    88. bool SFS12_SetNotFullCluster(char* _data,const unsigned short int _sectorsInCluster,const unsigned short int _indexCluster,const char* _clusterPart,const unsigned short int _clusterPartSize);
    89. bool SFS12_SetNotFullClusters(char* _data,const unsigned short int _sectorsInCluster,const unsigned short int _indexCluster,const unsigned short int _clustersCount,const char* _clusters,const unsigned short int _clusterPartSize);
    90.  
    91. bool SFS12_GetCluster(char* _cluster,const unsigned short int _sectorsInCluster,const char* _data,const unsigned short int _indexCluster);
    92. bool SFS12_GetClusters(char* _clusters,const unsigned short int _clustersCount,const unsigned short int _sectorsInCluster,const char* _data,const unsigned short int _indexCluster);
     
  11. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Я сейчас сделал так, что у меня есть структура BootSector (собственно она всегда и везде есть). В ней информация о дискете (количество цилиндров, дорожек на цилиндре, секторов на дорожке и байтов в секторе) и информация о файловой системе (идентификатор, описание, количество секторов в кластере, где начинаются резервные кластера, где начинается описание кластеров, где начинается (если она вообще есть) копия описания кластеров, где начинается корневая папка и статус последнего действия). Вот как она выглядела бы на ассемблере:

    Код (Text):
    1. jmpCode             db 0x00,0x00,0x00
    2. identifier          db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    3. description         db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    4. cylinders           db 0x00
    5. tracksInCylinder    db 0x00
    6. sectorsInTrack      db 0x00
    7. bytesInSector       dw 0x0000
    8. sectorsInCluster    db 0x00
    9. indexReserved       dw 0x0000
    10. indexClusters       dw 0x0000
    11. indexCopyClusters   dw 0x0000
    12. indexRootDirectory  dw 0x0000
    13. unfinishedAction    db 0x00
    14. code                db ; Тут код загрузочного сектора на 472 байта
    15. signature           db 0x00,0x00
    Описания кластеров - это двух байтный массив, элемент которого кое-что характеризует. Характеристика следующая:

    0x0000 - кластер свободен
    0x0FF7 - кластер с ошибкой
    0x0FF8 - кластер с загрузочным сектором
    0x0FF9 - последний кластер цепочки резервных кластеров
    0x0FFA - последний кластер цепочки характеристики кластеров
    0x0FFB - последний кластер цепочки копии характеристики кластеров
    0x0FFC - кластер с корневой директорией
    0x0FFD - последний кластер цепочки элементов корневой папки
    0x0FFE - последний кластер цепочки элементов папки
    0x0FFF - последний кластер цепочки данных файла

    Значение в диапазоне от 0x0001 до 0x0B3F означают индекс кластера. Значения в диапазоне от 0x0B40 до 0x0FF6 и от 0x1000 до 0xFFFF запрещены!

    И есть структура ObjectDescription где содержится описание объекта (папки/файла). Там указывается индекс кластера, где лежит список описаний объектов, среди которого есть и описание папки, к которой принадлежит данный объект. Если в качестве индекса родительского объекта стоит значение 0x0000, то данный объект лежит в корневой папке. Ну и дальше обычные поля для описания объекта. Ничего тут особенного нет. Единственное, что есть специальное поле status, которое говорит о том, удалён ли объект или нет из списка. То есть в FAT для этого использовался первый символ в имени, а у меня отдельное поле. Вот как она выглядела бы на ассемблере:

    Код (Text):
    1. status              db 0x00
    2. indexParent         dw 0x0000
    3. name                db ; Тут имя объекта на 24 байта
    4. expansion           db 0x00,0x00,0x00,0x00
    5. attributes          db 0x00
    6. size                dd 0x00000000
    7. createDate          db 0x00,0x00,0x00,0x00
    8. createTime          db 0x00,0x00,0x00,0x00
    9. readDate            db 0x00,0x00,0x00,0x00
    10. readTime            db 0x00,0x00,0x00,0x00
    11. writeDate           db 0x00,0x00,0x00,0x00
    12. writeTime           db 0x00,0x00,0x00,0x00
    13. indexData           dw 0x0000
    14. items               dw 0x0000
    В общем так вот всё и устроено. Сейчас для неё пишу программу, чтобы можно было создавать образ, создавать в нём папки и испортировать в них файлы.

    И что, разве плохая файловая система?