Путаница в APUE2 (о символической ссылке в UNIX) - PullRequest
2 голосов
/ 26 сентября 2011

Исходный текст приведен ниже. Он находится в разделе 4.22

Программа на рис. 4.24 переходит в конкретный каталог и затем вызывает getcwd для печати рабочего каталога.Если мы запустим программу, мы получим

$ ./a.out
cwd = /var/spool/uucppublic
$ ls -l /usr/spool
lrwxrwxrwx 1 root 12 Jan 31 07:57 /usr/spool -> ../var/spool

Обратите внимание, что chdir следует по символической ссылке, как мы ожидаем, из рисунка 4.17. Но когда он поднимается вверх по дереву каталогов, getcwd не имеет представления, когда он достигаеткаталог / var / spool, на который указывает символическая ссылка / usr / spool.Это характеристика символических ссылок.

Что на самом деле имеет в виду автор, говоря, что программа нажимает /var/spool?Какова характеристика символических ссылок, указанных автором?Я не очень понял.

Ответы [ 3 ]

2 голосов
/ 27 сентября 2011

Расширение того, что @undor_gongor написал:

Каждый процесс имеет текущий рабочий каталог.Он не сохраняется как путь к каталогу;это ссылка на сам каталог.

Если бы он был сохранен как имя пути, то работа функции getcwd() была бы тривиальной: просто напечатайте имя пути.Вместо этого он должен прочитать текущий каталог, открыть его запись .., затем открыть запись .. этого каталога и т. Д., Пока он не достигнет корня (т. Е. Каталог, запись которого .. указывает на сам каталог),При этом он создает полный путь к текущему каталогу в обратном порядке.

Поскольку .. не может быть символической ссылкой, символические ссылки не влияют на этот процесс.

(Оболочки могут иметь переменную $PWD или $CWD или встроенную pwd, на которую влияют символические ссылки; обычно они работают, запоминая строку, переданную cd или pushd.)

2 голосов
/ 27 сентября 2011

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

cd [-L|-P] [dir]

Изменить текущий каталог на dir.Переменная HOME является каталогом по умолчанию. [...] Опция -P говорит, что следует использовать физическую структуру каталогов вместо символьных ссылок (см. Также опцию -P для встроенной команды set);опция -L заставляет следовать символическим ссылкам.Аргумент - эквивалентен $ OLDPWD.Если используется непустое имя каталога из CDPATH, или если - является первым аргументом, и смена каталога прошла успешно, абсолютный путь нового рабочего каталога записывается в стандартный вывод.Возвращаемое значение равно true, если каталог был успешно изменен;иначе false.

В показанном сценарии, где /usr/spool является символической ссылкой на /var/spool, тогда:

$ pwd
/
$ cd /usr/spool/uucppublic
/usr/spool/uucppublic
$ cd -L ..
/usr/spool
$ cd /usr/spool/uucppublic
/usr/spool/uucppublic
$ cd -P ..
/var/spool
$

Для большинства людей простая cd ..будет делать так же, как cd -L ...Вы можете выбрать bash сделать то же самое, что и cd -P .., вместо этого, если вы предпочитаете (используя set -P или set -L).

Процесс поиска имени текущего каталога также следует понимать,Логически процесс (ядро) открывает текущий каталог (.) и считывает номер инода (и номер устройства).Затем он открывает родительский каталог (..) и считывает записи из него, пока не найдет один из них с соответствующим номером инода (и номером устройства).Это тогда дает ему последний компонент имени пути.Теперь он может повторять процесс, находя номер инода следующего каталога и открывая родительский каталог (../..) и т. Д., Пока не достигнет корневого каталога (где номер индекса для . и .. то же самое, и значение обычно 2).Обратите внимание, что это работает даже в точках монтирования.Остерегайтесь автоматически смонтированных удаленных (NFS) файловых систем;это может быть очень медленным, если вы сканируете каталог, содержащий несколько сотен автоматически подключенных машин - так как наивный план поиска выше монтирует все машины, пока не найдет правильный.Итак, фактические функции getcwd() умнее этого, но это объясняет, как найти путь к текущему каталогу.И это также показывает, почему процесс не встретит /usr/spool при оценке каталога в /var/spool/uucppublic - он просто никогда не откроет каталог /usr.

Обратите внимание, что функция realpath() (системный вызов) занимаетимя, возможно, ссылающееся на символические ссылки и преобразующее его в имя, которое вообще не содержит символических ссылок.Пройдя /usr/spool/uucppublic, он вернет /var/spool/uucppublic, например.

2 голосов
/ 26 сентября 2011

Предположим, у вас есть символическая ссылка /usr/spool, указывающая на /var/spool.

В нем говорится, что если вы перейдете по этой символической ссылке (например, cd /usr/spool), вы окажетесь в указанном каталоге (/var/spool).Затем информация, по которой вы переходили по символической ссылке, теряется.Вы находитесь в /var/spool, как если бы вы сделали cd /var/spool напрямую.

Еще cd .. приводит вас к /var (в отличие от /usr).

ОБНОВЛЕНИЕ :

Как указаноКит Томпсон и Джонатан Леффлер, есть несколько оболочек, которые делают помнят путь, которым вы следовали (то есть /usr/spool).В таких оболочках cd .. будет переходить к /usr/.Однако программы, запускаемые из такой оболочки, все равно будут видеть /var/spool в качестве рабочего каталога.

Возможно, именно поэтому автор позволил вам написать программу для отображения cwd (для обхода внутренних оболочек таких оболочек).

...