Скажем, я захожу в оболочку в системе Unix и начинаю нажимать на команды. Я изначально начинаю в домашнем каталоге моего пользователя ~
. Я мог бы оттуда cd
в каталог Documents
.
Команда для изменения рабочего каталога здесь очень проста для интуитивного понимания: у родительского узла есть список дочерних узлов, к которым он может получить доступ, и, вероятно, он использует (оптимизированный) вариант поиска, чтобы найти существование дочернего узла с введите имя пользователя, и затем рабочий каталог будет «изменен», чтобы соответствовать этому - поправьте меня, если я ошибаюсь. Может быть даже проще, что оболочка просто «наивно» пытается попытаться получить доступ к каталогу точно в соответствии с желаниями пользователя, и когда файловая система возвращает какой-либо тип ошибки, оболочка отображает ответ соответственно.
Однако меня интересует, как работает тот же процесс, когда я перемещаюсь вверх по каталогу, то есть к родителю или родителю родителя.
Учитывая мое неизвестное, предположительно «слепое» местоположение Documents
одного из, возможно, множества каталогов во всем дереве файловой системы с таким именем, как Unix определяет, где я должен быть расположен дальше? Делает ли это ссылку pwd
и исследовать это? Если да, как pwd
отслеживать текущее состояние навигации?
источник
Ответы:
Другие ответы - упрощения, каждый из которых представляет только часть истории, и они ошибочны в нескольких моментах.
Существует два способа отслеживания рабочего каталога:
chdir()
иfchdir()
системных вызовов, последний отchroot()
. Их можно увидеть косвенно в/proc
операционных системах Linux или с помощьюfstat
команды на FreeBSD и т. П.Когда выполняется разрешение имени пути, оно начинается с того или другого из указанных ссылочных vnodes, в зависимости от того, является ли путь относительным или абсолютным. (Существует семейство
…at()
системных вызовов, которые позволяют начинать разрешение имен с vnode, на который ссылается открытый (каталог) файловый дескриптор в качестве третьей опции.)В микроядерных Unices структура данных находится в прикладном пространстве, но принцип хранения открытых ссылок на эти каталоги остается прежним.
chdir()
.Если кто-то меняет относительный путь, он манипулирует строкой, чтобы добавить это имя. Если кто-то изменится на абсолютный путь, он заменит строку новым именем. В обоих случаях корректируется строка для удаления
.
и..
компонентов, а также для поиска символических ссылок, заменяя их связанными именами. ( Вот код оболочки Z для этого , например.)Имя во внутренней строковой переменной отслеживается переменной оболочки с именем
PWD
(илиcwd
в оболочках Си). Это обычно экспортируется как переменная окружения (именованнаяPWD
) в программы, порожденные оболочкой.Эти два метода отслеживания вещей выявлены с помощью
-P
и-L
опций кcd
иpwd
оболочки встроенных команд, а также различия между оболочками встроенныхpwd
команд и как/bin/pwd
команды и встроенныеpwd
команды вещей , как (среди прочих) ВИМ и НеоВИМ.Как вы можете видеть: получение «логического» рабочего каталога - это вопрос просмотра
PWD
переменной оболочки (или переменной среды, если она не является программой оболочки); тогда как получение «физического» рабочего каталога - это вызовgetcwd()
функции библиотеки.Работа
/bin/pwd
программы при использовании-L
опции несколько тонкая. Он не может доверять значениюPWD
переменной среды, которую он унаследовал. В конце концов, это не должно вызываться оболочкой, и промежуточные программы, возможно, не реализовали механизм оболочки, заставляющийPWD
переменную среды всегда отслеживать имя рабочего каталога. Или кто-то может сделать то, что я сделал только там.Таким образом, он выполняет (как говорит стандарт POSIX) проверку того, что имя, указанное в,
PWD
дает то же самое, что и имя.
, что можно увидеть с помощью трассировки системного вызова:Как видите: он вызывает только в
getcwd()
случае обнаружения несоответствия; и его можно одурачить, установивPWD
строку, которая действительно называет тот же каталог, но другим путем.Функция
getcwd()
библиотеки сама по себе является предметом. Но, прежде всего:..
каталоге. Он останавливался, когда достигал цикла, в котором..
был такой же рабочий каталог, или когда при попытке открыть следующий..
файл произошла ошибка . Это было бы много системных вызовов под прикрытием.Однако обратите внимание, что даже во FreeBSD и тех других операционных системах ядро не отслеживает рабочий каталог со строкой.
Навигация к
..
снова является отдельной темой. Еще один пример: хотя каталоги условно (хотя, как уже упоминалось, это не обязательно) содержат фактические..
данные в структуре данных каталога на диске, ядро отслеживает родительский каталог каждого vnode каталога и, таким образом, может перейти к..
vnode любого рабочий каталог. Это несколько усложняется точкой монтирования и измененными корневыми механизмами, которые выходят за рамки этого ответа.В сторону
Windows NT на самом деле делает то же самое. Для каждого процесса существует один рабочий каталог, установленный
SetCurrentDirectory()
вызовом API и отслеживаемый ядром для каждого процесса через (внутренний) дескриптор открытого файла для этого каталога; и есть набор переменных среды, которые программы Win32 (не только интерпретаторы команд, но и все программы Win32) используют для отслеживания имен нескольких рабочих каталогов (по одной на диск), добавляя или перезаписывая их при каждом изменении каталога.Традиционно, в отличие от случая с операционными системами Unix и Linux, программы Win32 не отображают эти переменные среды пользователям. Однако иногда их можно увидеть в Unix-подобных подсистемах, работающих в Windows NT, а также при использовании команд интерпретаторов
SET
команд определенным образом.дальнейшее чтение
pwd
" . Базовые спецификации открытых групп. Выпуск 7. IEEE 1003.1: 2008. Открытая группа. 2016.источник
..
в контексте Plan9,.
и..
компоненты, и выслеживает символические ссылки, заменяя их их связанными именами. ... Имя во внутренней строковой переменной отслеживается переменной оболочки с именемPWD
... »(выделение добавлено). … (Продолжение)PWD
=…/b
послеcd b
команды, даже еслиb
это символическая ссылка наa
- поэтому оболочка не «преследует»a -> b
ссылку. Вы ошиблись или я неправильно прочитал?CHASE_LINKS
.Ядро не отслеживает имена каталогов или файлов; файл или каталог представлены в ядре парой индекс / устройство. Системные вызовы , такие как
chdir()
,open()
и т.д. принять путь в качестве параметра, который может быть абсолютным (например/etc/passwd
), или относительно текущего каталога (примеры:Documents
,..
). Когда процесс выполняетсяchdir("Documents")
, поиск выполняетсяDocuments
в текущем рабочем каталоге, и рабочий каталог процесса обновляется для ссылки на этот каталог. С точки зрения ядра, в имени «..» нет ничего особенного, это просто соглашение в файловой системе, которое..
ссылается на родительский каталог.Эта
getcwd()
функция - не системный вызов, а библиотечная функция, которая должна пройти до корневого каталога, записывая имена компонентов пути на пути.источник
Интересно, что традиционно
cd ..
это намного намного проще, чемpwd
. Названные..
каталоги размещаются явно в файловой системе. Система отслеживает устройство / inode текущего каталога, такcd ..
что, точнее говоря, системный вызовchdir("..")
влечет за собой поиск имени «..» в файле, принадлежащем к inode текущего каталога, и замену устройства / inode текущего каталога на найденное там значение.pwd
(точнее/bin/pwd
)..
последовательно переходит по ссылкам и читает соответствующие каталоги до тех пор, пока не найдет индекс, откуда он взялся, собирая список этих имен в обратном порядке, пока он не достигнет корневого каталога (в частности, не содержащего..
записи).Теперь это оригинальное базовое поведение низкого уровня. Фактические команды оболочки
pwd
вместо этого полагаются на различные методы, кеширующие текущее имя пути. Но в сущности, на самом деле известен только его инод. Это подразумевает, что если для навигации по каталогам используются символические ссылки, то представления об имени текущего рабочего каталога в текущей оболочке и в системе/bin/pwd
могут расходиться.источник