Индексные дескрипторы, жёсткие и символические ссылки

⏱ 30 мин · 🧩 заданий: 5

Индексный дескриптор (inode)

В классических файловых системах Unix (ext2/3/4, UFS) у каждого файла есть индексный дескриптор — запись фиксированного размера в таблице inode на диске. Он хранит всё о файле, кроме имени:

Поле Значение
тип и права (mode) обычный файл, каталог, ссылка, устройство…; rwxrwxrwx, setuid…
владелец, группа UID, GID
размер в байтах
времена atime (доступ), mtime (изменение данных), ctime (изменение inode)
счётчик ссылок сколько записей каталогов указывают на этот inode
число блоков сколько места занято
адреса блоков данных прямые адреса, косвенные блоки (или экстенты в ext4)
для устройств номер устройства (major, minor)
inode (ext2) ┌───────────────────────┐ │ mode, uid, gid, size │ │ atime, mtime, ctime │ │ links_count = 2 │ │ блоки 0..11 (прямые) ─┼──▶ блоки данных │ косвенный ──┼──▶ блок адресов ──▶ блоки данных │ двойной косвенный ──┼──▶ блок адресов ──▶ блоки адресов ──▶ данные │ тройной косвенный ──┼──▶ ... └───────────────────────┘

Каталог: имя → номер inode

Каталог — файл, состоящий из записей «имя → номер inode». Имени в inode нет, поэтому у одного файла может быть несколько имён.

каталог /home/anna таблица inode этой ФС ┌──────────────┬────────┐ ┌───────┬──────────────────────┐ │ . │ 5001 │ │ 5001 │ каталог │ │ .. │ 2000 │ │ 7342 │ файл, links = 2, │ │ notes.txt │ 7342 │──┐ │ │ size 1200, блоки ... │ │ backup.txt │ 7342 │──┴────▶ │ │ │ └──────────────┴────────┘ └───────┴──────────────────────┘
ls -i                   # показать номера inode
stat notes.txt          # Links: 2

Жёсткие ссылки

Жёсткая ссылка — ещё одна запись каталога с тем же номером inode:

ln notes.txt backup.txt     # системный вызов link("notes.txt", "backup.txt")
  • оба имени равноправны — «оригинала» нет;
  • счётчик ссылок inode увеличивается;
  • rm (системный вызов unlink) удаляет имя и уменьшает счётчик;
  • inode и блоки освобождаются, когда счётчик ссылок = 0 и файл никем не открыт.

Почему нельзя на другое устройство

Это вопрос 4(в) экзамена.

Запись каталога содержит только номер inode — без указания устройства. Номер inode уникален лишь внутри одной файловой системы: на другом разделе под номером 7342 лежит совсем другой файл (или ничего). Поэтому жёсткая ссылка может указывать только на inode той же ФС. Ядро проверяет это в link(): если исходный файл и каталог для нового имени на разных смонтированных ФС — возвращается ошибка EXDEV («Invalid cross-device link»).

Ещё причины: счётчик ссылок хранится в inode на своём устройстве — другая ФС не может его изменить; при размонтировании одного раздела ссылка вела бы в никуда; разные ФС могут вообще не иметь понятия inode (FAT).

Тот же EXDEV возвращает rename() между разными ФС — поэтому mv между разделами на самом деле копирует и удаляет.

Также обычно нельзя создавать жёсткие ссылки на каталоги: появились бы циклы в дереве, и .. стало бы неоднозначным.

Символические ссылки

Символическая ссылка — отдельный маленький файл (свой inode, тип l), содержимое которого — путь:

ln -s /mnt/usb/data.txt link.txt     # symlink("/mnt/usb/data.txt", "link.txt")
ls -l link.txt
lrwxrwxrwx 1 anna anna 17 окт 25 link.txt -> /mnt/usb/data.txt
readlink link.txt
  • может указывать куда угодно: другая ФС, каталог, несуществующий файл;
  • при открытии ядро подставляет путь и продолжает поиск (с ограничением на число переходов — защита от циклов, ошибка ELOOP);
  • если цель удалить — ссылка «висит» (dangling).
Жёсткая Символическая
Что это ещё одно имя того же inode файл с путём
Свой inode нет да
Другая ФС нельзя (EXDEV) можно
На каталог нельзя можно
Удаление цели данные живы, пока есть имена ссылка висит

Удаление открытого файла

int fd = open("/tmp/tmpdata", O_RDWR | O_CREAT, 0600);
unlink("/tmp/tmpdata");     /* имени больше нет, но файл жив */
write(fd, buf, n);          /* работает */
close(fd);                  /* только теперь место освобождается */

Поэтому df может показывать занятое место после удаления большого журнала, если служба держит его открытым.

Итог

  • inode хранит всё о файле, кроме имени; каталог — таблица «имя → номер inode».
  • Жёсткая ссылка — ещё одно имя того же inode; счётчик ссылок; данные удаляются при 0 ссылок и 0 открытий.
  • Жёсткую ссылку нельзя сделать на другую ФС: номер inode уникален только внутри своей ФС, link() → EXDEV.
  • Символическая ссылка хранит путь и может вести куда угодно, но может «повиснуть».

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Один вариант ответа

Можно ли создать жёсткую ссылку на файл, находящийся на другом блочном устройстве (другой файловой системе)?

Задание 2 Ввод ответа

Файл a.txt имеет счётчик ссылок 1. Выполнили ln a.txt b.txt, затем rm a.txt. Каков счётчик ссылок у b.txt?

Задание 3 Заполнить таблицу

Жёсткая или символическая ссылка?

ЖёсткаяСимволическая
Ещё одна запись каталога с тем же номером inode
Отдельный файл (свой inode), содержащий путь
Может указывать на другую файловую систему
Увеличивает счётчик ссылок st_nlink
Становится «висячей», если цель удалили
Обычным пользователям нельзя создавать на каталоги
Отметьте ячейку — «+», пустая — «−».
Задание 4 Ввод ответа

Процесс открыл файл и, не закрывая его, вызвал unlink для единственного имени файла. Может ли процесс дальше читать файл? (да/нет)

Задание 5 Ввод ответа

Какой счётчик ссылок у только что созданного пустого каталога /tmp/d? (число)

Войдите, чтобы отмечать пройденные уроки.