По сути, мне нужно реализовать программу, которая будет действовать как файловая система пространства пользователя, которая реализует очень простые операции, такие как просмотр того, что находится на диске, копирование файлов в исходную файловую систему и из нее в мою файловую систему (которая содержится в одном файле). называется «disk01») и удаление файлов из моей файловой системы.
Я в основном ищу трамплин или какой-то намек на то, с чего начать, поскольку я не уверен, как создать свой собственный «диск» и поместить в него другие файлы, и это домашнее задание.
Просто студент C ++ ищет какое-то направление.
Редактировать:
Я знаю, что это концепция, которая уже используется в нескольких разных местах, таких как «VFS» или виртуальные файловые системы, вроде zip-файлов (вы можете просматривать содержимое только через программу, которая может обрабатывать zip-файлы). Я в основном пытаюсь написать свою собственную программу, похожую на zip или winrar или что-то еще, но не настолько сложную и многофункциональную.
Спасибо за ваши предложения до сих пор! Вы все — огромная помощь!
Создать FAT-подобную структуру диска очень просто.
В фиксированном месте в файле, скорее всего сначала, у вас есть структура с некоторой информацией о диске. Затем следует «FAT», таблица простых структур, детализирующих файлы на диске. Это в основном таблица с фиксированным размером структуры, подобная этой:
struct FATEntry
{
char name[20]; /* Name of file */
uint32_t pos; /* Position of file on disk (sector, block, something else) */
uint32_t size; /* Size in bytes of file */
uint32_t mtime; /* Time of last modification */
};
После этой таблицы у вас есть область фиксированного размера, используемая для растрового изображения свободных блоков на диске. Если файловая система может динамически увеличиваться или уменьшаться, то растровое изображение может не понадобиться. Затем следуют фактические данные файла.
Для такой системы все файлы должны постоянно размещаться на диске. Это приведет к фрагментации при добавлении, удалении и изменении размера файлов.
Другой способ — использовать подход со связанными списками, используемый, например, в старых файловых системах Amiga. По этой схеме все блоки представляют собой просто связанные списки.
Как и прежде, вам нужна структура для фактических данных на диске и, возможно, растровое изображение, показывающее свободные / выделенные блоки диска. Единственное поле, необходимое в структуре данных диска, — это «указатель» на первый файл.
Под указателем я подразумеваю целое число, указывающее местоположение на диске блока.
Сами файлы могут быть похожи на вышеуказанную FAT-подобную систему:
struct FileNode
{
char name[12]; /* Name of file */
uint32_t next; /* Next file, zero for last file */
uint32_t prev; /* Previous file, zero for first file */
uint32_t data; /* Link to first data block */
uint32_t mtime; /* Last modification time */
uint32_t size; /* Size in bytes of the file */
};
Блоки данных сами являются связанными списками:
struct DataNode
{
uint32_t next; /* Next data block for file, zero for last block */
char data[BLOCK_SIZE - 4]; /* Actual data, -4 for the block link */
};
Хорошая вещь о файловой системе со связанным списком — то, что она никогда не будет фрагментирована. Недостатки заключаются в том, что вам может потребоваться перепрыгнуть весь диск, чтобы извлечь блоки данных, и что блоки данных нельзя использовать полностью, так как им требуется как минимум одна ссылка на следующий блок данных.
Третий способ, распространенный в Unix-подобных системах, состоит в том, чтобы данные файла содержали набор ссылок на блоки данных. Тогда блоки данных не должны храниться непрерывно на диске. Он будет включать в себя некоторые из тех же недостатков, что и метод связанного списка, в том смысле, что блоки могут храниться по всему диску, а максимальный размер файла ограничен. Одним из преимуществ является то, что блоки данных могут быть полностью использованы.
Такая структура может выглядеть
struct FileNode
{
char name[16]; /* Name of file */
uint32_t size; /* Size in bytes of file */
uint32_t mtime; /* Last modification time of file */
uint32_t data[26]; /* Array of data-blocks */
};
Приведенная выше структура ограничивает максимальный размер файла до 26 блоков данных.
Откройте файл для неразрушающего чтения / записи. С фстримом это может быть fstream stream(filename)
,
Затем используйте функции поиска для перемещения по нему. Если вы используете C ++ Fstream это stream.seekg(position)
,
Тогда вы хотели бы двоичные функции чтения и записи, чтобы вы использовали stream.read(buffer, len)
а также stream.write(buffer, len)
,
Самый простой способ запустить файловую систему — выбрать размер блока. Большинство людей использовали 512 байт в старые времена. Вы можете сделать это или использовать 4K или сделать его полностью регулируемым. Затем вы откладываете блок в начале для карты свободного пространства. Это может быть бит на блок или если вы ленивый один байт на блок. Затем после этого у вас есть корневой каталог. FAT сделал это простым способом: это просто список имен, некоторые метаданные, такие как метки времени, размер файла и смещения блоков. Я думаю, что блоки FAT имели указатель на следующий блок в файле, чтобы он мог фрагментировать файл без необходимости выполнять дефрагментацию во время записи.
Итак, вы ищите каталог, находите файл, переходите к смещению и читаете блоки.
Реальные файловые системы усложняются в сложных задачах, таких как выделение блоков для файлов, чтобы у них было пространство для роста в конце, не теряя места. Обработка фрагментации. Хорошая производительность, когда несколько потоков или программ пишут одновременно. Надежное восстановление в случае неожиданных ошибок диска или потери питания.