Архитектура VFS, часть 2 — Inodes: что это и как с этим работать

—

от автора

Файл в линуксе — это не «имя на диске», а три отдельные сущности: запись в каталоге, inode и блоки данных. Понимание того, как они связаны, объясняет почти всё «странное» (нет) поведение файловой системы: почему df -h показывает свободное место, а файл не создаётся; почему удалённый файл продолжает занимать диск; почему перенос гигантского файла на 100 ГБ между папками происходит мгновенно.

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

Что конкретно мы сегодня изучим:

  1. Что такое Inodes? Что такое каталог?

  2. Как на самом деле Linux хранит файлы.

  3. Виды ссылок: хардлинки и симлинки.

  4. Команды для диагностики: как посмотреть inode, найти файл по номеру и понять, куда делось место.


1. Что такое Inode? Что такое каталог?

Inode (айноды или index node — «индексный дескриптор») — это структура данных, которая хранит всю служебную информацию о файле или каталоге. Однако не хранит его имя или содержимое.

В айноде хранится:

  1. Размер файла.

  2. Права доступа.

  3. Идентификаторы владельца и группы (UID и GID).

  4. Временные метки (время создания, изменения и последнего доступа — atime, mtime, ctime).

  5. Счётчик жёстких ссылок, указывающих на этот файл.

  6. Указатели на физические блоки диска, где реально лежат данные файла.

Структура (основные поля данных) айноды:

  1. File mode — Определяет тип файла (обычный файл, каталог, символическая ссылка, блочное устройство и тд) и права доступа к файлу для владельца, группы и остальных.

  2. Owner ID (UID) — идентификатор пользователя-владельца файла.

  3. Group ID (GID) — идентификатор группы, которой принадлежит файл.

  4. File Size (Размер файла) — размер файла в байтах.

  5. Links Count (Счетчик жестких ссылок) — количество жестких ссылок, указывающих на данный inode. Файл удаляется с диска только тогда, когда это значение становится равным 0.

  6. Timestamps (Временны́е метки) — включают сразу три поля:

    1. atime — время последнего открытия файла.

    2. mtime — время последнего изменения содержимого файла.

    3. ctime — время последнего изменения метаданных файла (например, смена прав, владельца).

    4. crtime — время создания файла. Встречается не везде, но есть в XFS, BTRFS.

  7. Block Pointers (Указатели на дисковые блоки) — поле фиксированного размера, которое указывает, где на диске физически хранятся данные файла. Указатели бывают разных типов, и у каждого свой механизм указания адресов:

    1. В прямых блоках это адрес блока с данными файла.

    2. В косвенных блоках это адрес служебного блока, который полностью заполнен точно такими же 32-битными числами (адресами следующего уровня).

Вы заметили, что имени файла в inode нет? Имя и связь с номером айноды хранятся внутри каталога, который сам по себе является отдельным файлом. О нём мы сегодня также поговорим.

Важные особенности:

  1. Уникальность. Каждый файл или каталог имеют свой уникальный номер inode в пределах данной файловой системы.

  2. Фиксированное количество. При форматировании диска создаётся таблица inode. Количество айнод ограничено.

  3. Проблема исчерпания. Если на вашем диске ещё полно свободного места, но закончились inode (обычно из-за огромного количества мелких файлов), система выдаст ошибку, что диск переполнен и создать новый файл нельзя.

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

Когда вы форматируете диск, всё его пространство разбивается на логические зоны. В самом начале диска резервируется фиксированное место под физические данные:

  1. Суперблок. Хранит общую информацию о файловой системе (размер, тип и тд)

  2. Таблица inode. Это непрерывная цепочка секторов диска, где упорядоченно друг за другом лежат пустые структуры данных. Первая айнода, вторая, тысячная, миллионная…

  3. Блоки данных. Всё оставшееся и самое большое пространство диска, где будут храниться ваши тексты, фото и видео.

По умолчанию утилиты форматирования(например, mkfs.ext4) рассчитывают количество айнод по формуле: 1 айнода на каждые 16 килобайт пространства диска. Через параметры это значение можно поменять, а некоторые файловые системы умеют создавать айноды динамически прямо в процессе работы, поэтому у них таблица inode не имеет фиксированного размера и не может «закончиться» раньше самого диска.

Что такое каталог?

С точки зрения файловой системы, каталог — это точно такой же файл, у которого есть свой inode. Но у содержимого (блоках данных) этого файла другая структура, чем у условных текстовых файлов.

Проблема: inode — это нумерованная структура данных, которая хранит метаданные файла, но не хранит имя. Как же нам обратиться к файлу, зная только его имя?

Для этого и нужен каталог: для того, чтобы связывать понятные человеку имена файла (например, passwords.txt) с их числовыми идентификаторами — именами inode.

Содержимое каталога — это таблица. Его блоки данных хранят простой список записей. Каждая запись состоит из двух основных полей:

[ Текстовое имя ] <-> [ Номер inode ]

Служебные записи

Внутри каждого каталога всегда есть две обязательные записи, которые напрямую завязаны на inode:

  • . (точка): Ссылается на номер inode этого же каталога.

  • .. (две точки): Ссылается на номер inode родительского каталога.

Именно поэтому у любого созданного каталога счетчик ссылок в метаданных inode всегда равен минимум 2 (сама ссылка из родительского каталога + запись . внутри него).

Пример: как ОС ищет файл /home/user/photo.jpg

Когда вы вызываете файл по его пути, ядро производит пошаговое обращение через цепочку каталогов:

  1. ОС обращается к корневому каталогу /. Его номер inode жестко зашит в файловой системе (обычно это inode N2)

  2. Читаются блоки данных корневого каталога, в которых ищется строка "home". Рядом с ней находится номер inode для этого каталога.

  3. ОС переходит к найденному inode каталога home, открывает его блоки данных и ищет там строку "user", получая следующий inode.

  4. Процесс повторяется для каталога user, где наконец находится строка "photo.jpg" и соответствующий ей inode самого файла.

  5. Из inode файла photo.jpg ОС считывает адреса физических блоков на диске и выдает вам его содержимое.


2. В итоге — как Linux хранит файлы?

Чтобы не дублировать раздел выше, подытожим:

В Linux всякий файл — это запись в каталоге + inode + блоки данных, на которые указывает inode.

Сделать из прочитанного можно следующие выводы:

  1. Файл можно удалить, только когда на него никто не ссылается. Если вы удалите имя файла из каталога, но этот файл сейчас открыт какой-то программой, инод и блоки данных останутся на диске. Файловая система окончательно сотрет инод и освободит блоки только тогда, когда Links Count (и из каталогов, и от запущенных процессов) станет равен нулю.

  2. Перемещение файла внутри одного раздела происходит мгновенно. Если вы переносите фильм весом 50 ГБ из папки в папку на одном диске, Linux не копирует байты. Он просто стирает запись [Имя] <-> [inode] в старом каталоге и создает её в новом. Сам файл спокойно лежит на диске и в ус не дует.


Ссылки: хардлинки и симлинки

Ссылки — это механизм файловый системы, позволяющий обращаться к одному и тому же файлу (оригиналу) или каталогу по разным именам или путям.

Ссылки делятся на два вида: жёсткие (Hard Links, хардлинки) и символические (Symbolic Links, симлинки)

Что такое жёсткие ссылки?

Жёсткая ссылка — это запись в каталоге, ссылающаяся на тот же айнод, что и её «оригинал». По факту — это просто новое имя для файла.

Отмечу, что после создания хардлинка понятия «оригинал» в строгом смысле нет. Оба имени равноправны. Ни одно из них не является «главным» — оба указывают на один inode, и в самом inode хранится счётчик ссылок (link count), который показывает, сколько имён сейчас ссылаются на него.

Создать хардлинк можно командой ln без дополнительных параметров (она создаёт их по умолчанию):

ln original.txt hard_link.txt

Небольшой пример того, как работает link count в нашем случае:

  1. Создали file1 — inode с link count = 1.

  2. Сделали ln file1 file2 — link count = 2, оба имени равнозначны.

  3. Удалили file1 (rm file1) — link count = 1, данные по-прежнему доступны через file2.

  4. Удалили file2 — link count = 0, inode и блоки данных освобождаются.

Именно поэтому понятие «оригинал» здесь больше условность. С точки зрения ФС это просто два имени одного inode

Итоги:

  1. Жёсткие ссылки не занимают место под данные — только запись в каталоге (несколько байт). Поэтому ими пользуются для экономии места.

  2. Жёсткие ссылки нельзя делать на каталоги — это создало бы циклы, когда каталог обращается сам к себе или своему родителю.

  3. Жёсткие ссылки не работают между разными файловыми системами — потому что номер inode уникален только в пределах одной ФС.

  4. Изменение содержимого через любое имя видно через все остальные — ведь данные и метаданные одни и те же.

  5. Права и владелец тоже общие — изменили chmod через file2, изменилось и для file1.

Что такое символические ссылки?

Символическая ссылка — это отдельный файл с отдельной айнодой, содержащий в себе путь к целевому файлу или каталогу. Аналогия: ярлык в Windows.

Целевой файл/каталог — это файл/каталог, на который указывает символическая ссылка.

Чем символическая ссылка отличается от обычного файла с путём внутри? Внутри айноды этого файла, в поле File mode, ставится флаг S_IFLNK. Именно по этому флагу ядро мгновенно понимает, что перед нами не данные, а указатель, и чтение нужно перенаправить.

Симлинк — это текстовый файл-путеводитель. Когда вы или любая программа открываете симлинк, ядро Linux смотрит внутрь него, видит там строку с путем (например, /var/log/app.log) и автоматически переводит фокус на этот целевой файл. Для программ этот процесс прозрачен: они думают, что работают с реальным файлом, но на самом деле работают через ссылку.

Создать симлинк можно командой ln с параметром -s:

ln -s original.txt softlink.txt

В отличие от хардлинков, симлинки могут указывать на каталоги:

ln -s original_folder/ soft_folder/

Чтобы увидеть более наглядные примеры взаимодействия с симлинками, очень рекомендую эту статью: https://habr.com/ru/companies/timeweb/articles/925150/

Что будет, если удалить/переместить целевой файл? В таком случае символическая ссылка станет «висячей» и при попытке обратиться к ней программа получит ошибку No such file or directory.

Важные выводы и особенности:

  1. Так как симлинк — отдельный файл с отдельной айнодой, у него есть свои права доступа. Права на сам симлинк не имеют значения. Ядро при обращении проверяет права целевого файла, на который симлинк указывает.

  2. Симлинки могут указывать как на файлы, так и на каталоги, а также работать между разными файловыми системами или разделами.

  3. При удалении или перемещении целевого файла симлинк не удаляется автоматически, а становится «битым» или «висячим», так как строка пути внутри него начинает указывать на несуществующий объект.

  4. В современных файловых системах существует оптимизация Fast Symlinks: если длина пути меньше 60 символов, строка записывается прямо внутрь айноды симлинка, благодаря чему он вообще не занимает блоки на диске и считывается мгновенно.

  5. Путь внутри симлинка может быть абсолютным (весь путь от корневого каталога) или относительным (адрес файла относительно каталога, где находится симлинк)

Практика: команды для диагностики

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

1. Общая диагностика

# Простейший способ для просмотра использования айнод на всех смонтированных ФС$ df -i# Проверяет использование места на диске (чтобы убедиться, чтобы проблемы действительно в айнодах)$ df -h# Выводит 10 папок с самым большим количеством файлов (то есть айнод) в текущем каталоге$ find . -printf '%h\n' | sort | uniq -c | sort -rn | head -10# Подсчитывает количество айнод в текущем каталоге$ find . | wc -l

2. Получение номера айноды

# Узнать номер айноды файла$ ls -i <path/to/file># Посмотреть полные метаданные файла$ stat <path/to/file># Выводит список файлов текущего каталога и номера айнод первым столбцом$ ls -li

3. Работа с файлами по номеру айноды

# Найти файл на диске по номеру айноды$ sudo find / -inum <inode_number># Удалить файл по его айноде$ find . -inum <inode_number> -delete# Позволяет выполнить с файлом любую команду по номеру его айноды$ find <path/to/file> -inum <inode_number> -exec <command> {} \;

Источники

  1. https://man.archlinux.org/man/inode.7.en

  2. https://adminvps.ru/blog/chto-takoe-inody-inode-v-linux-prostoe-i-podrobnoe-rukovodstvo/

  3. https://habr.com/ru/companies/timeweb/articles/925150/

  4. https://habr.com/ru/articles/1017290/

  5. Нейросеть DeepSeek — консультация.

  6. Нейросеть Gemini — консультация.

ссылка на оригинал статьи https://habr.com/ru/articles/1104884/