# Отчет по дисциплине «Операционные системы» ## РГР «Разработка простой файловой системы» **Выполнил:** ____________________ **Группа:** ____________________ **Проверил:** ____________________ **Новосибирск, 2026** ## Оглавление 1. [Введение](#введение) 2. [Постановка задачи](#постановка-задачи) 3. [Выбранная архитектура файловой системы](#выбранная-архитектура-файловой-системы) 4. [Структура носителя и основные данные](#структура-носителя-и-основные-данные) 5. [Реализованные операции](#реализованные-операции) 6. [Алгоритмы работы](#алгоритмы-работы) 7. [Тестирование](#тестирование) 8. [Ограничения реализации](#ограничения-реализации) 9. [Вывод](#вывод) ## Введение Цель работы — разработать учебную файловую систему на языке C, использующую обычный бинарный файл как виртуальный носитель произвольного доступа. Программа должна не только хранить файлы и каталоги, но и показывать основные принципы настоящих файловых систем: разметку носителя, учет свободного места, хранение метаданных, работу с путями и прикладные операции обслуживания. В качестве ориентира использовался предоставленный пример реализации, однако приоритет был отдан требованиям задания. Поэтому итоговая программа сохраняет простую учебную архитектуру примера, но дополнительно реализует операции `open`, `close`, `seek`, `read`, `write`, `rename`, импорт и экспорт, дефрагментацию и сжатие. ## Постановка задачи Согласно заданию необходимо разработать систему управления файлами, где разделом является бинарный файл произвольного доступа. Реализация должна включать: - физический уровень хранения данных; - структуру учета свободных блоков; - базовый уровень с индексными метаданными; - размещение содержимого файлов; - систему каталогов и путей; - символьные операции над файлами и каталогами; - прикладную утилиту для форматирования, просмотра, импорта, экспорта, дефрагментации и сжатия. ## Выбранная архитектура файловой системы Файловая система разделена на уровни. Такое деление полезно не только для описания в отчете: каждый уровень решает свою задачу и скрывает детали от следующего. Пользователь работает с командами и путями, а не с номерами кластеров; функции чтения работают с файлами, а не с отдельными битами карты свободного пространства. | Уровень | Реализация | Назначение | | --- | --- | --- | | Физический уровень | Кластеры фиксированного размера по 1024 байта | Делит носитель на одинаковые адресуемые блоки; смещение кластера вычисляется как `номер * 1024` | | Учет свободного места | Битовая карта | Показывает, какие кластеры свободны, а какие уже принадлежат служебным областям или файлам | | Базовый уровень | Индексный файл с дескрипторами объектов | Хранит метаданные файлов и каталогов отдельно от пользовательских данных | | Размещение файлов | Список номеров кластеров в дескрипторе | Позволяет файлу занимать несколько несмежных кластеров и читать их в правильном порядке | | Логический уровень | Неупорядоченный список имен | Представляет каталоги через связь «объект — родительский каталог» и выполняет линейный поиск по именам | | Символьный уровень | Пути вида `/docs/file.txt`, буферизированные операции `open/close/seek/read/write` | Преобразует удобные человеку имена и позиции в обращения к дескрипторам и кластерам | | Прикладной уровень | Интерактивная консольная утилита | Дает команды для форматирования, просмотра, копирования, импорта, экспорта, сжатия и дефрагментации | ### Физический уровень Носителем является обычный бинарный файл. Он рассматривается как последовательность кластеров одинакового размера. Фиксированный размер выбран ради простоты: адрес любого кластера находится прямым умножением, а алгоритм выделения не обязан искать переменные по длине участки памяти. Недостатком является внутреннее фрагментирование: даже файл в несколько байт занимает целый кластер. ### Уровень свободного пространства Для каждого кластера хранится один бит. При форматировании служебные кластеры суперблока, битовой карты и индексного файла сразу помечаются занятыми. При записи файла функция выделения просматривает карту от начала области данных и выбирает первые свободные кластеры; при удалении файла соответствующие биты сбрасываются обратно в ноль. ### Базовый уровень Индексный файл — это таблица дескрипторов `Entry`. Один дескриптор описывает один файл или каталог: имя, тип, родителя, размеры и список кластеров. Корневой каталог хранится в нулевой записи. Благодаря индексному файлу метаданные можно прочитать сразу после монтирования носителя, не просматривая всю область данных. ### Уровень размещения файлов Каждый файл хранит массив номеров своих кластеров. Поэтому файл может лежать не непрерывно, а частями в разных местах виртуального диска. При чтении система идет по этому массиву и собирает содержимое в правильной последовательности. Дефрагментация перестраивает эти списки так, чтобы занятые кластеры снова располагались компактно. ### Логический и символьный уровни Каталог реализован без отдельного файла содержимого: у каждого объекта есть поле `parent`, содержащее индекс родительского каталога. Путь разбивается по символу `/`, после чего система шаг за шагом ищет дочерний объект в текущем каталоге. Символьный уровень дает привычные операции над открытым файлом: `open`, `close`, `seek`, `read`, `write`; внутри программы они работают через буфер и скрывают детали физического размещения. ```mermaid flowchart LR A[Команда пользователя] --> B[Путь /docs/a.txt] B --> C[Поиск дескриптора] C --> D[Список кластеров] D --> E[Битовая карта] D --> F[Байты в области данных] ``` ## Структура носителя и основные данные В начале виртуального диска находится суперблок. Он хранит сигнатуру файловой системы, размер диска, размер кластера, смещения служебных областей и индекс корневого каталога. ```c typedef struct { uint32_t magic; uint32_t disk_size; uint32_t cluster_size; uint32_t total_clusters; uint32_t bitmap_offset; uint32_t bitmap_size; uint32_t index_offset; uint32_t index_clusters; uint32_t data_start_cluster; uint32_t root_index; } SuperBlock; ``` После суперблока располагается битовая карта. Каждый ее бит соответствует одному кластеру: `0` означает свободный кластер, `1` — занятый. Далее находится индексный файл, представленный массивом дескрипторов `Entry`. ```c typedef struct { char name[32]; uint8_t type; uint8_t compressed; uint32_t parent; uint32_t size; uint32_t stored_size; uint32_t cluster_count; uint32_t clusters[128]; } Entry; ``` Поле `size` хранит логический размер файла, видимый пользователю, а `stored_size` — фактическое количество байт на носителе. Это различие необходимо для поддержки сжатых файлов. ```mermaid flowchart TB S[Суперблок] --> B[Битовая карта] B --> I[Индексный файл] I --> D[Область данных] I --> R[Корневой каталог /] R --> F[Дескрипторы файлов и каталогов] F --> D ``` ## Реализованные операции Программа собирается из файла `simplefs.c` и запускается с именем файла-носителя: ```bash gcc -std=c11 -Wall -Wextra -pedantic simplefs.c -o simplefs ./simplefs disk.img ``` Интерактивная оболочка поддерживает историю команд: в обычном терминале стрелки **Up** и **Down** перемещаются по ранее введенным строкам. Основные команды названы в стиле Unix, чтобы работа с учебной файловой системой напоминала привычную командную строку. ### Справочник команд | Команда | Синтаксис | Назначение | | --- | --- | --- | | Форматирование | `format ` | создает новый файл-носитель указанного размера | | Информация | `info` | показывает размер диска, размер кластера и число свободных кластеров | | Список | `ls [path]` | выводит содержимое текущего или указанного каталога | | Текущий каталог | `pwd` | печатает текущий абсолютный путь | | Переход | `cd ` | меняет текущий каталог | | Создание каталога | `mkdir ` | создает новый каталог | | Удаление каталога | `rmdir ` | удаляет только пустой каталог | | Создание файла | `touch ` | создает пустой файл | | Удаление файла | `rm ` | удаляет файл и освобождает его кластеры | | Копирование внутри ФС | `cp ` | копирует файл в новый путь или в существующий каталог | | Перемещение/переименование | `mv ` | переносит файл или каталог; если меняется только имя, работает как переименование | | Запись текста | `write ` | перезаписывает файл текстовой строкой | | Просмотр файла | `cat ` | выводит логическое содержимое файла | | Просмотр хранения | `rawcat ` | выводит физически сохраненные байты и объясняет пары RLE | | Импорт файла | `import ` | копирует файл из основной ОС в учебную ФС | | Экспорт файла | `export ` | копирует файл из учебной ФС в основную ОС | | Импорт папки | `importdir ` | рекурсивно импортирует каталог | | Экспорт папки | `exportdir ` | рекурсивно экспортирует каталог | | Экспорт носителя | `savecarrier ` | сохраняет копию всего бинарного носителя | | Импорт носителя | `loadcarrier ` | заменяет текущий носитель ранее сохраненной копией | | Сжатие | `compress ` | применяет RLE-сжатие, если оно уменьшает файл | | Распаковка | `decomp ` | восстанавливает файл в несжатом виде | | Дефрагментация | `defrag` | заново записывает файлы подряд в область данных | | Справка и выход | `help`, `exit`, `quit` | показывает команды или завершает программу | На уровне программного интерфейса реализованы функции `fs_open`, `fs_close`, `fs_seek`, `fs_read` и `fs_write`. Открытый файл использует буфер в памяти, поэтому чтение и запись записей произвольной длины выполняются без прямой работы пользователя с кластерами. ## Алгоритмы работы ### Форматирование При выполнении `format` создается бинарный файл нужного размера, вычисляются размеры служебных областей, резервируются занятые кластеры и создается корневой каталог `/`. ### Выделение свободного кластера Алгоритм линейно просматривает битовую карту, начиная с области данных. Первый свободный бит помечается как занятый, а номер соответствующего кластера возвращается вызывающей функции. ### Работа с каталогами Каталог не хранит отдельный массив дочерних элементов. Вместо этого у каждого дескриптора есть поле `parent`, содержащее индекс родительского каталога. Для поиска элемента программа просматривает индексный файл и сравнивает имя и родителя. ### Сжатие Команда `compress` использует простой алгоритм RLE: одинаковые подряд идущие байты заменяются парой «количество + значение». Если сжатый вариант не меньше исходного, файл не изменяется. При чтении сжатый файл автоматически восстанавливается в обычный вид. Для наблюдения за внутренним представлением предусмотрена команда `rawcat`: она показывает сохраненные байты в шестнадцатеричном виде и расшифровывает каждую RLE-пару. Команда `decomp` выполняет обратное преобразование и снова сохраняет файл без сжатия. ### Дефрагментация Команда `defrag` временно считывает содержимое файлов, очищает карту размещения области данных и записывает файлы заново подряд. После операции используемые кластеры становятся компактно расположенными. ## Тестирование Пример базового сценария: ```text format 512 mkdir /docs touch /docs/a.txt write /docs/a.txt aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa cat /docs/a.txt compress /docs/a.txt ls /docs rename /docs/a.txt b.txt export /docs/b.txt exported.txt defrag info ``` Ожидаемые результаты: | Проверка | Результат | | --- | --- | | Форматирование носителя | создается корректный виртуальный диск | | Создание каталога и файла | объекты появляются в `ls` | | Запись и чтение | `cat` выводит ранее записанный текст | | Сжатие повторяющихся данных | `stored_size` становится меньше `size` | | Переименование | файл доступен под новым именем | | Экспорт | создается внешний файл с тем же содержимым | | Дефрагментация | содержимое файлов сохраняется, кластеры уплотняются | ## Ограничения реализации | Ограничение | Причина | | --- | --- | | Не более 128 объектов | фиксированный размер индексного файла | | Не более 128 кластеров на файл | фиксированный массив номеров кластеров | | Длина имени до 31 символа | размер поля `name[32]` | | Линейный поиск по каталогу | выбрана простая неупорядоченная структура | | RLE эффективно не для всех данных | алгоритм выбран ради понятности реализации | | Нет одновременного доступа нескольких процессов | учебная однопользовательская модель | ## Вывод В ходе работы была реализована простая файловая система, работающая поверх бинарного файла как виртуального носителя. Реализация охватывает все основные уровни, указанные в задании: физическое размещение, учет свободных блоков, индексные метаданные, каталоги, операции над файлами и сервисные команды управления носителем. Полученная программа остается достаточно простой для изучения начинающим разработчиком на C, но при этом показывает полный путь данных: от пользовательской команды до изменения битовой карты, индексного дескриптора и байтов в кластерах виртуального диска.