TARFS 0.1.5
Read-only TAR filesystem for ESP32
Loading...
Searching...
No Matches
TARFS — файловая система только для чтения поверх TAR-архивов с поддержкой mmap()

Как создать и прошить свою файловую систему, инструкция.

Часто Задаваемые Вопросы (FAQ).

Нативный API.

1. Введение

TARFS — это лёгкая файловая система только для чтения, разработанная специально для встраиваемых устройств.

Образ файловой системы представляет собой обычный TAR-архив, созданный стандартной утилитой GNU tar.

Вместо того чтобы реализовывать полноценную файловую систему с записью, TARFS предоставляет прямой zero-copy доступ к стандартным POSIX TAR-архивам, расположенным во Flash-памяти и отображённым в адресное пространство (memory-mapped Flash). Файлы практически любого размера можно читать без дополнительных затрат оперативной памяти, при этом пользоваться привычными POSIX-интерфейсами и обычными TAR-утилитами.

Большинство файлов, входящих в состав прошивки, после её сборки уже никогда не меняются. HTML-страницы, CSS, JavaScript, изображения, сертификаты, шрифты, словари, таблицы, модели машинного обучения и прочие ресурсы обычно создаются ещё во время сборки проекта и затем только читаются. Использовать для хранения таких данных полноценную файловую систему с поддержкой записи зачастую просто нет смысла.


2. Зачем ещё одна файловая система?

1. Эффективное хранение неизменяемых данных на устройствах с небольшим объёмом памяти

Типичные примеры — ресурсы пользовательского интерфейса, иконки, содержимое встроенного HTTP-сервера, шрифты, сертификаты и другие подобные файлы.

TARFS оптимизирована для хранения большого количества файлов, которые никогда не изменяются, и обеспечивает их быстрый поиск.

2. Упрощение портирования программ, написанных под Linux

Многие программы ожидают увидеть файловую систему с более-менее POSIX-совместимым API. Например, PH7 PHP Engine для ESP32 использует mmap(), чтобы выполнять PHP-скрипты прямо из файлов.

Поскольку TARFS реализует настоящий zero-copy mmap(), приложения могут работать с файлами практически любого размера, не расходуя дополнительную оперативную память.

3. Более высокая устойчивость к повреждениям

Даже если часть файловой системы окажется повреждена, TARFS обычно всё равно сможет смонтировать архив и предоставить доступ к тем файлам, которые остались целыми. Каждый объект файловой системы может быть проверен отдельно с помощью встроенной контрольной суммы CRC.


3. Возможности

3.1 Ничего революционного

TARFS не вводит собственного формата файловой системы. Она просто предоставляет достаточно совместимый с POSIX интерфейс поверх обычного TAR-архива. POSIX здесь касается именно API, а не внутреннего формата хранения.

Библиотека написана на языке C, требует всего одного платформозависимого исходного файла и рассчитана на микроконтроллеры, которые умеют отображать Flash-память в адресное пространство процессора.

Подходящие платформы:

  • STM32
  • RP2040
  • SAMD21/SAMD51
  • nRF52
  • RA4M1 (Arduino UNO R4)
  • LPC17xx/LPC55xx
  • и многие другие микроконтроллеры.

Сам TAR-архив может находиться во внешней Flash-памяти, во внутреннем разделе Flash либо вообще быть встроен непосредственно в образ прошивки средствами компоновщика.

Можно ли использовать TARFS для монтирования файловой системы из секции .rodata прошивки? Да, можно. Например, на ESP32 вы можете встроить TAR-архив в образ прошивки с помощью механизма EMBED_FILES, а затем смонтировать его напрямую из памяти с помощью функции tarfs_mount_from_memory().


3.2 Использование памяти

TARFS рассчитана на микроконтроллеры с небольшим объёмом оперативной памяти.

На каждый файл или каталог требуется 24 байта RAM. Файловая система из тысячи объектов занимает чуть меньше 24 КБ оперативной памяти.

Количество одновременно открытых отображений mmap() никак не ограничено, поскольку mmap() вообще ничего не выделяет. Функция просто возвращает указатель на соответствующее место внутри архива.

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

Во время обычной работы TARFS вообще не использует динамическое выделение памяти. Выделение памяти происходит только при выполнении mount() и unmount().

Поскольку при монтировании выполняются всего несколько выделений памяти из кучи (как правило - два, но если есть symlinks с UTF8 именами - то чуть больше), проблема её фрагментации практически отсутствует.


3.3 POSIX-совместимость лучше, чем у существующих файловых систем ESP-IDF

TARFS поддерживает настоящий zero-copy mmap(). Содержимое файлов становится доступно напрямую через память, без копирования в RAM.

Поддерживаются:

  • statvfs()
  • dupfd()
  • fdopendir()
  • mmap()
  • символические ссылки, жёсткие ссылки и Windows Junction (если они присутствуют в TAR-архиве)
  • имена файлов, каталогов и ссылок в UTF-8
  • открытие каталогов через open()

3.4 Проверка целостности файлов (CRC64/ECMA-182)

Каждая запись TAR может содержать контрольную сумму CRC64/ECMA-182 без нарушения совместимости с форматом TAR.

Контрольные суммы записываются в неиспользуемые поля заголовка, поэтому архив остаётся полностью совместимым со всеми стандартными TAR-утилитами.

Утилита tarsum.c вычисляет CRC64 для каждой записи архива с ненулевым размером данных (включая записи, которые не являются обычными файлами) и сохраняет результат в свободной области заголовка.


3.5 Устойчивость к повреждениям

В отличие от большинства традиционных файловых систем, TARFS не имеет центрального суперблока.

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

Во время монтирования повреждённые записи просто пропускаются, а остальные файлы продолжают работать.

Кроме того, TARFS спокойно относится к забытым вызовам munmap(). Поскольку mmap() не выделяет память и не создаёт никаких системных ресурсов, пропущенный munmap() не приводит ни к утечкам памяти, ни к исчерпанию каких-либо ресурсов.


3.6 Производительность и предсказуемость

За исключением mount() и unmount(), TARFS вообще не использует примитивы синхронизации.

Весь рабочий путь выполнения реализован без блокировок (lock-free). Некоторые состояния гонки теоретически возможны, но они возникают только в строго определённых ситуациях и подробно описаны в документации.

Поиск файлов выполняется бинарным поиском по хэшу имени.

Для работы readdir() и связанных функций таблица inode одновременно отсортирована и по хэшу, и в лексикографическом порядке.

Операция Сложность Примечание
mount() O(3N log N) Три прохода по архиву и обработка ссылок
open(), opendir() O(log N) Бинарный поиск
readlink() O(k) k — общее число символических и жёстких ссылок
read(), mmap(), close(), lseek() и др. O(1) Прямой доступ по заранее вычисленным указателям
readdir(), telldir() и др. O(1) Последовательный обход по заранее подготовленным связям