Индексные дескрипторы, жёсткие и символические ссылки
Индексный дескриптор (inode)
В классических файловых системах Unix (ext2/3/4, UFS) у каждого файла есть индексный дескриптор — запись фиксированного размера в таблице inode на диске. Он хранит всё о файле, кроме имени:
| Поле | Значение |
|---|---|
тип и права (mode) |
обычный файл, каталог, ссылка, устройство…; rwxrwxrwx, setuid… |
| владелец, группа | UID, GID |
| размер | в байтах |
| времена | atime (доступ), mtime (изменение данных), ctime (изменение inode) |
| счётчик ссылок | сколько записей каталогов указывают на этот inode |
| число блоков | сколько места занято |
| адреса блоков данных | прямые адреса, косвенные блоки (или экстенты в ext4) |
| для устройств | номер устройства (major, minor) |
Каталог: имя → номер inode
Каталог — файл, состоящий из записей «имя → номер inode». Имени в inode нет, поэтому у одного файла может быть несколько имён.
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
Можно ли создать жёсткую ссылку на файл, находящийся на другом блочном устройстве (другой файловой системе)?
Файл a.txt имеет счётчик ссылок 1. Выполнили ln a.txt b.txt, затем rm a.txt.
Каков счётчик ссылок у b.txt?
Жёсткая или символическая ссылка?
| Жёсткая | Символическая | |
|---|---|---|
| Ещё одна запись каталога с тем же номером inode | ||
| Отдельный файл (свой inode), содержащий путь | ||
| Может указывать на другую файловую систему | ||
| Увеличивает счётчик ссылок st_nlink | ||
| Становится «висячей», если цель удалили | ||
| Обычным пользователям нельзя создавать на каталоги |
Процесс открыл файл и, не закрывая его, вызвал unlink для единственного имени файла.
Может ли процесс дальше читать файл? (да/нет)
Какой счётчик ссылок у только что созданного пустого каталога /tmp/d? (число)
Войдите, чтобы отмечать пройденные уроки.