Inne odpowiedzi są uproszczeniami, z których każda przedstawia tylko fragmenty historii i są błędne w kilku punktach.
Istnieją dwa sposoby śledzenia katalogu roboczego:
- Dla każdego procesu w strukturze danych przestrzeni jądra, która reprezentuje ten proces, jądro przechowuje dwa odwołania vnode do vnodes katalogu roboczego i katalogu głównego dla tego procesu. Pierwsze odniesienie jest ustawione przez wywołania systemowe
chdir()
i fchdir()
, drugie przez chroot()
. Można je zobaczyć pośrednio w /proc
systemach operacyjnych Linux lub za pomocą fstat
polecenia na FreeBSD i tym podobnych:% fstat -p $$ | head -n 5
UŻYTKOWNIK CMD PID FD MOUNT INUM MODE SZ | DV R / W
JdeBP zsh 92648 text / 24958 -r-xr-xr-x 702360 r
JdeBP zsh 92648 ctty / dev 148 crw - w ---- pts / 4 rw
JdeBP zsh 92648 wd / usr / home / JdeBP 4 drwxr-xr-x 124 r
JdeBP zsh 92648 root / 4 drwxr-xr-x 35 r
%
Kiedy działa rozpoznawanie nazw ścieżek, zaczyna się od jednego lub drugiego z tych przywoływanych vnodes, w zależności od tego, czy ścieżka jest względna czy bezwzględna. (Istnieje rodzina …at()
wywołań systemowych, które umożliwiają rozpoznawanie nazw ścieżek rozpoczynające się od vnode, do którego odwołuje się deskryptor pliku otwartego (katalogu) jako trzecia opcja).
W mikrojądrach Unices struktura danych znajduje się w przestrzeni aplikacji, ale zasada utrzymywania otwartych odniesień do tych katalogów pozostaje taka sama.
- Wewnętrznie, w powłokach takich jak powłoka Z, Korn, Bourne Again, C i Almquist, powłoka dodatkowo śledzi katalog roboczy za pomocą manipulacji ciągiem wewnętrznej zmiennej łańcuchowej. Robi to za każdym razem, gdy ma powód do połączenia
chdir()
.Jeśli ktoś zmieni się na względną nazwę ścieżki, manipuluje ciągiem, aby dodać tę nazwę. Jeśli ktoś zmieni bezwzględną nazwę ścieżki, zastępuje ciąg nową nazwą. W obu przypadkach dostosowuje ciąg do usunięcia .
i ..
komponentów oraz do ścigania dowiązań symbolicznych, zastępując je nazwami połączonymi z nimi. ( Oto przykładowy kod powłoki Z. )
Nazwa w wewnętrznej zmiennej łańcucha jest śledzona przez zmienną powłoki o nazwie PWD
(lub cwd
w powłokach C). Jest to konwencjonalnie eksportowane jako zmienna środowiskowa (o nazwie PWD
) do programów spawnowanych przez powłokę.
Te dwie metody śledzenia rzeczy są ujawniane przez -P
i -L
opcje do cd
i pwd
powłoki wbudowanych komend i różnicami między muszli wbudowanych pwd
poleceń i zarówno /bin/pwd
polecenia i wbudowanych pwd
poleceń rzeczy jak (między innymi) VIM i NeoVIM.
% mkdir a; ln -sab
% (cd b; pwd; / bin / pwd; printenv PWD)
/ usr / home / JdeBP / b
/ usr / home / JdeBP / a
/ usr / home / JdeBP / b
% (cd b; pwd -P; / bin / pwd -P)
/ usr / home / JdeBP / a
/ usr / home / JdeBP / a
% (cd b; pwd -L; / bin / pwd -L)
/ usr / home / JdeBP / b
/ usr / home / JdeBP / b
% (cd-P b; pwd; / bin / pwd; printenv PWD)
/ usr / home / JdeBP / a
/ usr / home / JdeBP / a
/ usr / home / JdeBP / a
% (cd b; PWD = / hello / there / bin / pwd -L)
/ usr / home / JdeBP / a
%
Jak widać: uzyskanie „logicznego” katalogu roboczego polega na spojrzeniu na PWD
zmienną powłoki (lub zmienną środowiskową, jeśli nie jest to program powłoki); podczas gdy uzyskanie „fizycznego” katalogu roboczego jest kwestią wywołania getcwd()
funkcji biblioteki.
Działanie /bin/pwd
programu, gdy -L
używana jest opcja, jest nieco subtelne. Nie może ufać wartości PWD
odziedziczonej zmiennej środowiskowej. W końcu nie musiała być wywoływana przez powłokę, a interweniujące programy mogły nie wdrożyć mechanizmu powłoki polegającego na tym, że PWD
zmienna środowiskowa zawsze śledzi nazwę katalogu roboczego. Albo ktoś może zrobić to, co właśnie tam zrobiłem.
Więc to, co robi (jak mówi standard POSIX), sprawdza, czy nazwa podana w PWD
daje to samo co nazwa .
, co można zobaczyć za pomocą śledzenia wywołania systemowego:
% ln -sac
% (cd b; truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ usr / home / JdeBP / b", { mode = drwxr-xr-x, inode = 120932, size = 2, blksize = 131072}) = 0 (0x0)
stat (".", {mode = drwxr-xr-x, inode = 120932, size = 2, blksize = 131072}) = 0 (0x0)
/ usr / home / JdeBP / b
% (cd b; PWD = / usr / local / etc truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ usr / local / etc" , {mode = drwxr-xr-x, i-węzeł = 14835, rozmiar = 158, rozmiar blks = 10240}) = 0 (0x0)
stat (".", {mode = drwxr-xr-x, i-węzeł = 120932, rozmiar = 2 , blksize = 131072}) = 0 (0x0)
__getcwd ("/ usr / home / JdeBP / a", 1024) = 0 (0x0)
/ usr / home / JdeBP / a
% (cd b; PWD = / hello / there truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ hello / there", 0x7fffffffe730) ERR # 2 „Brak takiego pliku lub katalogu”
__getcwd („/ usr / home / JdeBP / a”, 1024) = 0 (0x0)
/ usr / home / JdeBP / a
% (cd b; PWD = / usr / home / JdeBP / c truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ usr / home / JdeBP / c ", {mode = drwxr-xr-x, inode = 120932, size = 2, blksize = 131072}) = 0 (0x0)
stat (". ", {Mode = drwxr-xr-x, inode = 120932 , rozmiar = 2, rozmiar blks = 131072}) = 0 (0x0)
/ usr / home / JdeBP / c
%
Jak widać: wywołuje tylko getcwd()
wtedy, gdy wykryje niezgodność; i można go oszukać, ustawiając PWD
ciąg znaków, który rzeczywiście nazywa ten sam katalog, ale inną drogą.
Funkcja getcwd()
biblioteczna jest odrębnym przedmiotem. Ale aby to zrobić:
Nawigacja do ..
jest znowu osobnym tematem. Kolejna zasada: chociaż katalogi konwencjonalnie (choć, jak już wspomniano, nie jest to wymagane) zawierają rzeczywistą ..
strukturę danych katalogu na dysku, jądro śledzi katalog macierzysty każdego vnode katalogu i może w ten sposób nawigować do ..
vnode dowolnego katalog roboczy. Jest to nieco skomplikowane przez punkt montowania i zmienione mechanizmy rootowania, które są poza zakresem tej odpowiedzi.
Na bok
Windows NT faktycznie robi podobne rzeczy. Istnieje jeden katalog roboczy na proces, ustawiony przez SetCurrentDirectory()
wywołanie API i śledzony na proces przez jądro za pomocą (wewnętrznego) dojścia do otwartego pliku do tego katalogu; i istnieje zestaw zmiennych środowiskowych, które programy Win32 (nie tylko interpreter poleceń, ale wszystkie programy Win32) używają do śledzenia nazw wielu działających katalogów (jednego na dysk), dołączając je lub zastępując przy każdej zmianie katalogu.
Konwencjonalnie, w przeciwieństwie do systemów operacyjnych Unix i Linux, programy Win32 nie wyświetlają tych zmiennych środowiskowych użytkownikom. Czasem można je zobaczyć w podsystemach uniksopodobnych działających w systemie Windows NT, a także przy użyciu poleceń interpretera SET
poleceń w określony sposób.
Dalsza lektura