22 KiB
Отчет по дисциплине «Операционные системы»
РГР «Разработка простой файловой системы»
Выполнил: ____________________
Группа: ____________________
Проверил: ____________________
Новосибирск, 2026
Оглавление
- Введение
- Постановка задачи
- Выбранная архитектура файловой системы
- Структура носителя и основные данные
- Реализованные операции
- Алгоритмы работы
- Тестирование
- Ограничения реализации
- Вывод
Введение
Цель работы — разработать учебную файловую систему на языке C, использующую обычный бинарный файл как виртуальный носитель произвольного доступа. Программа должна не только хранить файлы и каталоги, но и показывать основные принципы настоящих файловых систем: разметку носителя, учет свободного места, хранение метаданных, работу с путями и прикладные операции обслуживания.
В качестве ориентира использовался предоставленный пример реализации, однако приоритет был отдан требованиям задания. Поэтому итоговая программа сохраняет простую учебную архитектуру примера, но дополнительно реализует операции open, close, seek, read, write, rename, импорт и экспорт, дефрагментацию и сжатие.
Постановка задачи
Согласно заданию необходимо разработать систему управления файлами, где разделом является бинарный файл произвольного доступа. Реализация должна включать:
- физический уровень хранения данных;
- структуру учета свободных блоков;
- базовый уровень с индексными метаданными;
- размещение содержимого файлов;
- систему каталогов и путей;
- символьные операции над файлами и каталогами;
- прикладную утилиту для форматирования, просмотра, импорта, экспорта, дефрагментации и сжатия.
Выбранная архитектура файловой системы
Файловая система разделена на уровни. Такое деление полезно не только для описания в отчете: каждый уровень решает свою задачу и скрывает детали от следующего. Пользователь работает с командами и путями, а не с номерами кластеров; функции чтения работают с файлами, а не с отдельными битами карты свободного пространства.
| Уровень | Реализация | Назначение |
|---|---|---|
| Физический уровень | Кластеры фиксированного размера по 1024 байта | Делит носитель на одинаковые адресуемые блоки; смещение кластера вычисляется как номер * 1024 |
| Учет свободного места | Битовая карта | Показывает, какие кластеры свободны, а какие уже принадлежат служебным областям или файлам |
| Базовый уровень | Индексный файл с дескрипторами объектов | Хранит метаданные файлов и каталогов отдельно от пользовательских данных |
| Размещение файлов | Список номеров кластеров в дескрипторе | Позволяет файлу занимать несколько несмежных кластеров и читать их в правильном порядке |
| Логический уровень | Неупорядоченный список имен | Представляет каталоги через связь «объект — родительский каталог» и выполняет линейный поиск по именам |
| Символьный уровень | Пути вида /docs/file.txt, буферизированные операции open/close/seek/read/write |
Преобразует удобные человеку имена и позиции в обращения к дескрипторам и кластерам |
| Прикладной уровень | Интерактивная консольная утилита | Дает команды для форматирования, просмотра, копирования, импорта, экспорта, сжатия и дефрагментации |
Физический уровень
Носителем является обычный бинарный файл. Он рассматривается как последовательность кластеров одинакового размера. Фиксированный размер выбран ради простоты: адрес любого кластера находится прямым умножением, а алгоритм выделения не обязан искать переменные по длине участки памяти. Недостатком является внутреннее фрагментирование: даже файл в несколько байт занимает целый кластер.
Уровень свободного пространства
Для каждого кластера хранится один бит. При форматировании служебные кластеры суперблока, битовой карты и индексного файла сразу помечаются занятыми. При записи файла функция выделения просматривает карту от начала области данных и выбирает первые свободные кластеры; при удалении файла соответствующие биты сбрасываются обратно в ноль.
Базовый уровень
Индексный файл — это таблица дескрипторов Entry. Один дескриптор описывает один файл или каталог: имя, тип, родителя, размеры и список кластеров. Корневой каталог хранится в нулевой записи. Благодаря индексному файлу метаданные можно прочитать сразу после монтирования носителя, не просматривая всю область данных.
Уровень размещения файлов
Каждый файл хранит массив номеров своих кластеров. Поэтому файл может лежать не непрерывно, а частями в разных местах виртуального диска. При чтении система идет по этому массиву и собирает содержимое в правильной последовательности. Дефрагментация перестраивает эти списки так, чтобы занятые кластеры снова располагались компактно.
Логический и символьный уровни
Каталог реализован без отдельного файла содержимого: у каждого объекта есть поле parent, содержащее индекс родительского каталога. Путь разбивается по символу /, после чего система шаг за шагом ищет дочерний объект в текущем каталоге. Символьный уровень дает привычные операции над открытым файлом: open, close, seek, read, write; внутри программы они работают через буфер и скрывают детали физического размещения.
flowchart LR
A[Команда пользователя] --> B[Путь /docs/a.txt]
B --> C[Поиск дескриптора]
C --> D[Список кластеров]
D --> E[Битовая карта]
D --> F[Байты в области данных]
Структура носителя и основные данные
В начале виртуального диска находится суперблок. Он хранит сигнатуру файловой системы, размер диска, размер кластера, смещения служебных областей и индекс корневого каталога.
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.
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 — фактическое количество байт на носителе. Это различие необходимо для поддержки сжатых файлов.
flowchart TB
S[Суперблок] --> B[Битовая карта]
B --> I[Индексный файл]
I --> D[Область данных]
I --> R[Корневой каталог /]
R --> F[Дескрипторы файлов и каталогов]
F --> D
Реализованные операции
Программа собирается из файла simplefs.c и запускается с именем файла-носителя:
gcc -std=c11 -Wall -Wextra -pedantic simplefs.c -o simplefs
./simplefs disk.img
Интерактивная оболочка поддерживает историю команд: в обычном терминале стрелки Up и Down перемещаются по ранее введенным строкам. Основные команды названы в стиле Unix, чтобы работа с учебной файловой системой напоминала привычную командную строку.
Справочник команд
| Команда | Синтаксис | Назначение |
|---|---|---|
| Форматирование | format <KiB> |
создает новый файл-носитель указанного размера |
| Информация | info |
показывает размер диска, размер кластера и число свободных кластеров |
| Список | ls [path] |
выводит содержимое текущего или указанного каталога |
| Текущий каталог | pwd |
печатает текущий абсолютный путь |
| Переход | cd <path> |
меняет текущий каталог |
| Создание каталога | mkdir <path> |
создает новый каталог |
| Удаление каталога | rmdir <path> |
удаляет только пустой каталог |
| Создание файла | touch <path> |
создает пустой файл |
| Удаление файла | rm <path> |
удаляет файл и освобождает его кластеры |
| Копирование внутри ФС | cp <from> <to> |
копирует файл в новый путь или в существующий каталог |
| Перемещение/переименование | mv <from> <to> |
переносит файл или каталог; если меняется только имя, работает как переименование |
| Запись текста | write <path> <text> |
перезаписывает файл текстовой строкой |
| Просмотр файла | cat <path> |
выводит логическое содержимое файла |
| Просмотр хранения | rawcat <path> |
выводит физически сохраненные байты и объясняет пары RLE |
| Импорт файла | import <host_file> <fs_path> |
копирует файл из основной ОС в учебную ФС |
| Экспорт файла | export <fs_path> <host_file> |
копирует файл из учебной ФС в основную ОС |
| Импорт папки | importdir <host_dir> <fs_path> |
рекурсивно импортирует каталог |
| Экспорт папки | exportdir <fs_path> <host_dir> |
рекурсивно экспортирует каталог |
| Экспорт носителя | savecarrier <host_file> |
сохраняет копию всего бинарного носителя |
| Импорт носителя | loadcarrier <host_file> |
заменяет текущий носитель ранее сохраненной копией |
| Сжатие | compress <path> |
применяет RLE-сжатие, если оно уменьшает файл |
| Распаковка | decomp <path> |
восстанавливает файл в несжатом виде |
| Дефрагментация | defrag |
заново записывает файлы подряд в область данных |
| Справка и выход | help, exit, quit |
показывает команды или завершает программу |
На уровне программного интерфейса реализованы функции fs_open, fs_close, fs_seek, fs_read и fs_write. Открытый файл использует буфер в памяти, поэтому чтение и запись записей произвольной длины выполняются без прямой работы пользователя с кластерами.
Алгоритмы работы
Форматирование
При выполнении format создается бинарный файл нужного размера, вычисляются размеры служебных областей, резервируются занятые кластеры и создается корневой каталог /.
Выделение свободного кластера
Алгоритм линейно просматривает битовую карту, начиная с области данных. Первый свободный бит помечается как занятый, а номер соответствующего кластера возвращается вызывающей функции.
Работа с каталогами
Каталог не хранит отдельный массив дочерних элементов. Вместо этого у каждого дескриптора есть поле parent, содержащее индекс родительского каталога. Для поиска элемента программа просматривает индексный файл и сравнивает имя и родителя.
Сжатие
Команда compress использует простой алгоритм RLE: одинаковые подряд идущие байты заменяются парой «количество + значение». Если сжатый вариант не меньше исходного, файл не изменяется. При чтении сжатый файл автоматически восстанавливается в обычный вид. Для наблюдения за внутренним представлением предусмотрена команда rawcat: она показывает сохраненные байты в шестнадцатеричном виде и расшифровывает каждую RLE-пару. Команда decomp выполняет обратное преобразование и снова сохраняет файл без сжатия.
Дефрагментация
Команда defrag временно считывает содержимое файлов, очищает карту размещения области данных и записывает файлы заново подряд. После операции используемые кластеры становятся компактно расположенными.
Тестирование
Пример базового сценария:
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, но при этом показывает полный путь данных: от пользовательской команды до изменения битовой карты, индексного дескриптора и байтов в кластерах виртуального диска.