Каталог как файл-список имен других файлов, которым сопоставлены номера индексных дескрипторов, не запрещает иметь два разных имени файла, указывающих на одни и те же метаданные . Такой эффект носит название жесткой ссылки, создать которую можно при помощи команды ln.
Содержимое
Жесткая ссылка
john@ubuntu:~$ touch readme
john@ubuntu:~$ ls -li readme
20318653 -rw-r—r— 1 john john 0 ноя. 1 01:32 readme
john@ubuntu:~$ ln readme readme.txt
john@ubuntu:~$ touch README
john@ubuntu:~$ ls -li readne readme.txt README
20318653 -rw-r—r— 2 john john 0 ноя. 1 01:32 readme
20319121 -rw-r—r— 1 john john 0 ноя. 1 01:33 README
20318653 -rw-r—r— 2 john john 0 ноя. 1 01:32 readme.txt
Более того, оба имени являются равнозначными, и нет возможности узнать, какое из них создано первым, из чего нужно заключить, что первое и единственное имя файла уже является его жесткой ссылкой (на номер индексного дескриптора).
При добавлении файлу нового имени (жесткой ссылки) в его метаданных увеличивается счетчик количества имен, а при удалении файла сначала удаляется имя и уменьшается счетчик количества имен, и только при удалении последнего имени высвобождаются метаданные и данные файла.
Счетчик имен файла
john@ubuntu:~$ ln readme read.me
john@ubuntu:~$ ls -li read*
20318653 -rw-r—r— 3 john john 0 ноя. 1 01:32 readme
20318653 -rw-r—r— 3 john john 0 ноя. 1 01:32 read.me
20318653 -rw-r—r- — 3 john john 0 ноя. 1 01:32 readme.txt
john@ubuntu:~$ rm readme
john@ubuntu:~$ ls -li read*
20318653 -rw-r—r— 2 john john 0 ноя. 1 01:32 read.me
20318653 -rw-r—r— 2 john john 0 ноя. 1 01:32 readme.txt
john@ubuntu:~$ rm readme.txt
john@ubuntu:~$ ls -li read*
20318653 -rw-r—r— 1 john john 0 ноя. 1 01:32 read.me
Удаление открытого файла
Нужно заметить, что удаление файла — двухшаговая операция, состоящая из удаления имени файла, а затем — удаления метаданных (и высвобождения блоков, занимавшихся этим файлом).
Удаление метаданных файла не выполняется вообще, если у файла еще остались имена (жесткие ссылки), и не происходит сразу, если файл открыт каким-либо процессом.
Метаданные и блоки, занимаемые файлом, высвобождаются только при закрытии этого файла всеми открывшими его процессами, что проиллюстрировано в примере ниже.
Команда df измеряет доступное (свободное, disk free) место на файловой системе указанного файла, тогда как команда du, наоборот, измеряет занимаемое (disk usage) указанным файлом место на его файловой системе.
john@ubuntu:~$ df -h .
Файл.система Размер Использовано Дост Использовано% Смонтировано в
/dev/mapper/ubuntu-root 455G 400G 32G 93% /
john@ubuntu:~$ du -sh astra-linux-l.3-special-edition-snolensk-disk3-devel.iso
2,8G astra-linux-l.3-special-edition-snolensk-disk3-devel.iso
john@@ubuntu:~$ rm astra-linux-l.3-special-edition-snolensk-disk3-devel.iso
john@ubuntu:~$ df -h .
Файл.система Размер Использовано Дост Использовано% Смонтировано в
/dev/mapper/ubuntu-root 455G 400G 32G 93% /
finn@ubuntu:~$ lsof astra-linux-l.3-special-editrion-snolensk-disk3-devel.iso
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
fuseiso 16925 john 3r REG 252,0 2947385344 20316584 astra-linux-1.3-special-edition-
snolensk-disk3-devel.iso
john@ubuntu:~$ kill 16925
john@ubuntu:~$ df -h .
Файл.система Размер Использовано Дост Использовано% Смонтировано в
/dev/mapper/ubuntu-root 455G 397G 35G 92% /
Специальные имена текущего . и родительского . . каталога на поверку тоже оказываются жесткими ссылками, поэтому у любого каталога по крайней мере два имени — свое «собственное» в родительском и специальное . в самом себе, а у каталогов с подкаталогами еще и имена . . в каждом из дочерних.
Имена каталогов
john@ubuntu:~$ mkdir folder
john@ubuntu:~$ ls -ldi folder
20357139 drwxr-xr-x 2 john john 4096 апр. 1 01:58 folder
john@ubuntu:~$ cd folder
john@ubuntu:~/folder$ ls -lai
итого 8
20357139 drwxr-xr-x 2 john john 4096 ноя. 1 01:58 .
20332580 drwxr-xr-x 4 john john 4096 ноя. 1 01:58 . .
john@ubuntu:~/folder$ mkdir child
john@ubuntu:~/folder$ cd child
john@ubuntu:~/folder/chlld$ ls -lai
итого 8
20357140 drwxr-xr-x 2 john john 4096 ноя. 1 02:01 .
20357139 drwxr-xr-x 3 john john 4096 ноя. 1 02:01 . .
john@ubuntu:~/folder/chlld$ cd . ./. .
john@ubuntu:~$ stat folder/
Файл: «folder/»
Размер: 4096 Блоков: 8 Блок B/B: 4096 каталог
Устройство: fc00h/64512d Inode: 20357139 Ссылки: 3
. . . . . . . . .
john@ubuntu:~$ rmdir folder
rmdlr: не удалось удалить «folder»: Каталог не пуст
Существенным ограничением жесткой ссылки в дереве каталогов, куда смонтирована более чем одна файловая система, является локальность жесткой ссылки в пределах своей файловой системы в силу локальной значимости номеров индексных дескрипторов.
Так как на каждой новой файловой системе номера индексных дескрипторов начинают нумероваться с нуля, то жесткая ссылка всегда указывает на метаданные файла в «своей» файловой системе и не может указывать на метаданные файла в «чужой» файловой системе общего дерева каталогов.
Для преодоления этого ограничения служит символическая ссылка symlink, являющаяся самостоятельным служебным типом и содержащая путевое имя к целевому файлу.
Символическая ссылка
john@ubuntu:~$ ln -s read.me readme.1st
john@ubuntu:~$ ls -li read*
20318653 -rw-r—r— 1 john john 0 ноя. 1 01:32 read.me
20319944 lrwxrwxrwx 1 john john 6 ноя. 2 00:02 readme.1st -> read.me ★
В случае с символической ссылкой при удалении целевого файла сама ссылка будет указывать в никуда и называться «сиротой» (orhpan). Попытка прочитать такую ссылку приводит к странным, на первый взгляд, результатам: файл «существует» для команды ls, но команда просмотра содержимого Cat говорит об обратном. Ничего удивительного, если помнить, что ls работает с именами файлов, a cat — с их данными (которые действительно не существуют).
Сиротская ссылка
john@ubuntu:~$ rm read.me
john@ubuntu:~$ ls read*
readme.1st
john@ubuntu:~$ cat readme.1st
cat: readme.1st: Нет такого файла или каталога
john@ubuntu:~$ ls -l read*
Irwxrwxrwx 1 john john 6 ноя. 2 00:02 readme.1st -> read.me
john@ubuntu:~$ cat read.me
cat: read.me: Нет такого файла или каталога
Символические ссылки могут ссылаться на имена друг друга неограниченное количество раз, а при попытке использовать одну из таких ссылок будут использованы данные файла, последнего в цепочке ссылок. По ошибке можно даже закольцевать две или более ссылок, с чем разберется операционная система при чтении одной из ссылок.
Кольцевые ссылки
john@ubuntu:~$ ln -s readme.1st read.me
john@ubuntu:~$ ls -l read*
lrwxrwxrwx 1 john john 10 ноя. 2 00:42 read.me -> readme.1st
lrwxrwxrwx 1 john john 8 ноя. 2 00:04 readme.1st -> read.me
john@ubuntu:~$ cat read.me
cat: read.me: Слишком много уровней символьных ссылок
Основным назначением символических (и изначально, жестких) ссылок является «множественная каталогизация» файлов, т.е. разные наборы разных имен одних и тех же данных. Типичным примером использования ссылок является организация boot сценариев запуска системных служб при старте операционной системы. Сами сценарии располагаются в каталоге /etc/lnit.d, а в каталогах /etc/rcS.d, /etc/rc0.d, …, /etc/rc6.d размещены символические ссылки на эти сценарии, которые должны быть запущены с определенными параметрами при переключении состояния системы между так называемыми «уровнями исполнения» runlevel.
Сценарии запуска служб и их каталогизация по уровням исполнения
john@ubuntu:~$ ls -l /etc/rc?1.d
/etc/rc2.d:
lrwxrwxrwx 1 root root 20 окт. 12 2018 /etc/rc2.d/S19postgresql -> .. /init.d/postgresql
lrwxrwxrwx 1 root root 17 ноя. 31 2018 /etc/rc2.d/S20postflx -> ../init.d/postftx
/etc/rc6.d:
lrwxrwxrwx 1 root root 17 ноя. 31 2018 /etc/rc6.d/K20postftx -> . ./init.d/postftx
lrwxrwxrwx 1 root root 20 окт. 12 2018 /etc/rc6.d/K21postgresql -> ../init.d/postgresql
В этом примере сценарии postfix и postgresql имеют вторичные имена, начинающиеся с K в каталоге rc6.d, и другие вторичные имена, начинающиеся с S в каталоге rc2.d. Это символизирует необходимость запускать (start) службы postfix и postgresql при переключении системы на уровень исполнения № 2 и уничтожать (kill) процессы этих служб при переключении системы на уровень исполнения № 6.