Стандарт SUSv3 требует, чтобы реализация допускала по меньшей мере _POSIX_SYMLOOP_MAX разыменований для каждого компонента символической ссылки имени пути. Указанное значение _POSIX_SYMLOOP_MAX равно 8. Однако до версии ядра 2.6.18 Linux допускала не более пяти разыменований при следовании по цепочке символических ссылок. Начиная с указанной версии, Linux реализует минимальное число разыменований (8), указанное в стандарте SUSv3. Linux допускает также для всего имени пути общее число разыменований, равное 40. Эти пределы необходимы, чтобы избежать очень длинных цепочек из символических и циклических ссылок, вызывающих переполнение стека ядра при их анализе.
Ряд файловых систем UNIX осуществляют оптимизацию, не упомянутую в основном тексте и не показанную на рис. 18.2. Когда общая длина строки, образующей содержимое символической ссылки, достаточно мала для того, чтобы уместиться в той части индексного дескриптора, которая обычно используется для указателей на данные, строка ссылки хранится там. Это позволяет избежать выделения блока на диске, а также ускоряет доступ к информации символической ссылки, поскольку она извлекается вместе с индексным дескриптором файла. Так, например, файловые системы ext2, ext3 и ext4 применяют данный метод для встраивания коротких символических строк в пределах 60 байт, которые обычно применяются для указателей на блоки данных. На практике такая оптимизация может оказаться весьма эффективной. Среди 20 700 символических ссылок в одной системе, исследованной автором, 97 % имели размер 60 байт и менее.
Многие системные вызовы разыменовывают символические ссылки (следуют по ним) и таким образом работают с файлом, на который указывает ссылка. Отдельные вызовы не разыменовывают, а оперируют непосредственно ссылкой. При рассмотрении каждого системного вызова мы описываем его поведение по отношению к символическим ссылкам. Эти сведения подытожены также в табл. 18.1.
Таблица 18.1. Интерпретация символических ссылок различными функциями
Функция
Следует ли по ссылкам?
Примечания
access()
*
acct()
*
bind()
*
Сокеты домена UNIX имеют имена путей
chdir()
*
chmod()
*
chown()
*
chroot()
*
creat()
exec()
*
getxattr()
lchown()
lgetxattr()
link()
См. раздел 18.3
listxattr()
*
llistxattr()
lremovexattr()
lsetxattr()
lstat()
lutimes()
open()
*
Если не указан флаг O_NOFOLLOW или O_EXCL | O_CREAT
opendir()
*
pathconf()
*
pivot_root()
*
quotactl()
*
readlink()
removexattr()
*
rename()
Ссылки не отслеживаются ни в одном из аргументов
rmdir()
Завершается с ошибкой ENOTDIR, если аргумент является символической ссылкой
setxattr()
*
stat()
*
statfs(), statvfs()
*
swapon(), swapoff()
*
truncate()
*
unlink()
uselib()
*
utime(), utimes()
*
В ряде случаев, когда необходимо обеспечить одинаковое функционирование как для файла, с которым соотносится символическая ссылка, так и для нее самой, применяют взаимоисключающие системные вызовы: один из них разыменовывает ссылку, а второй — нет, причем этот вызов снабжен префиксом в виде буквы l; например: stat() и lstat().
Обычно выполняется следующее: символические ссылки, являющиеся частью имени пути, представляющей каталоги (то есть все компоненты, которые предшествуют завершающему слешу), всегда разыменовываются. Так, в имени пути /somedir/somesubdir/file компоненты somedir и somesubdir всегда будут разыменованы, если являются символическими ссылками, а разыменование компонента file будет зависеть от того, какому системному вызову было передано имя пути.
В разделе 18.11 мы описываем набор системных вызовов, добавленных в версии Linux 2.6.16. Они расширяют функциональность ряда интерфейсов, приведенных в табл. 18.1. Для некоторых из этих системных вызовов можно управлять вариантами обработки символических ссылок с помощью аргумента flags.