Diğer cevaplar, her biri hikayenin sadece bölümlerini sunan, aşırı basitleştirmelerdir ve birkaç noktada yanlıştır.
Çalışma dizininin izlendiği iki yol vardır :
- Her işlem için, bu işlemi temsil eden çekirdek-alan veri yapısında, çekirdek, çalışma dizininin vnodlarına ve o işlemin kök dizinine iki vnode referansı depolar. Eski başvuru ile ayarlanır
chdir()ve fchdir()sistem çağrıları, ikincisi chroot(). Bunları dolaylı /procolarak Linux işletim sistemlerinde ya da fstatFreeBSD ve benzeri komutlarla görebilirsiniz:% fstat -p $$ | head -n 5
KULLANICI CMD PID FD MONTAJ MODELİ SZ | DV R / W
JdeBP zsh 92648 metin / 24958 -r-xr-xr-x 702360 r
JdeBP zsh 92648 ctty / dev 148 crw - w ---- puan / 4 rw
JdeBP zsh 92648 wd / usr / ana sayfa / JdeBP 4 drwxr-xr-x 124 r
JdeBP zsh 92648 kökü / 4 drwxr-xr-x 35 r
%
Yol adı özünürlüğü çalıştığında, yolun göreceli veya mutlak olmasına bağlı olarak başvurulan vnotlardan biri veya diğerinden başlar. ( …at()Açık (dizin) dosya tanıtıcısının üçüncü bir seçenek olarak başvuru yaptığı vnode'da yol adı çözümlemesinin başlamasını sağlayan bir sistem çağrısı ailesi vardır .)
Mikro çekirdek Unices'de veri yapısı uygulama alanındadır, ancak bu dizinlere açık referanslar tutma prensibi aynı kalmaktadır.
- Dahili olarak, örneğin Z, Korn, Bourne Yine, C ve Almquist kabuk kabukları içinde, kabuk ek bir iç dize değişkeni dize işlemleri kullanarak çalışma dizini izler. Bunu, aramaya neden olduğu zaman yapar
chdir().Biri göreceli bir yol adına değişirse, o ismi eklemek için dizgiyi değiştirir. Eğer biri mutlak yol ismine geçerse, dizeyi yeni isimle değiştirir. Her iki durumda da, dizeyi çıkarmak .ve ..bileşenleri kaldırmak ve onları bağlantılı isimleri ile değiştirmek yerine sembolik bağları kovalamak için ayarlar . ( Örneğin , Z kabuğunun bunun kodu .)
İç string değişkenindeki isim, PWD(veya cwdC kabuklarında) isimli bir kabuk değişkeni ile izlenir . Bu, geleneksel olarak PWDkabuk tarafından oluşturulan programlara bir ortam değişkeni (adında ) olarak verilir.
İzleme şeylerin Bu iki yöntem ile ortaya çıkar -Pve -Lseçenekler cdve pwdkabuk dahili komutları ve yerleşik kabukları arasındaki farklılıklardan pwdkomutlar ve her iki /bin/pwdkomuta ve yerleşik pwdgibi şeylerin komutları (diğerleri arasında) VIM ve NeoVIM.
% mkdir a;
% -sab % ( cdb ; pwd; / bin / pwd; printenv PWD)
/ Usr / home / JdeBP / b
/ Usr / home / JdeBP / a
/ Usr / home / JdeBP / b
% (cdb; pwd -P; / bin / pwd -P)
/ Usr / home / JdeBP / a
/ Usr / home / JdeBP / a
% (cdb; pwd-L; / bin / pwd -L)
/ Usr / home / JdeBP / b
/ Usr / home / JdeBP / b
% (cd-Pb; pwd; / bin / pwd; printenv PWD)
/ Usr / home / JdeBP / a
/ Usr / home / JdeBP / a
/ Usr / home / JdeBP / a
% (cd b; PWD = / merhaba / orada / bin / pwd -L)
/ Usr / home / JdeBP / a
%
Gördüğünüz gibi: "mantıksal" çalışma dizinini edinmek, PWDkabuk değişkenine (ya da kabuk programı değilse çevre değişkeni) bakmaktan ibarettir; "fiziksel" çalışma dizinini edinmek ise getcwd()kitaplık işlevini çağırmaktan ibarettir.
Seçenek kullanıldığında /bin/pwdprogramın çalışması -Lbiraz incedir. Bu güvenemiyorum değerini PWDmiras ettiğini ortam değişkeni. Sonuçta, bir kabuk tarafından çağrılması gerekmedi ve araya giren programların kabuğun PWDçevre değişkenini her zaman çalışan dizinin adını izlemesini sağlayan mekanizma uygulamamış olabilir . Ya da biri orada yaptığımı yapabilir.
Öyleyse, (POSIX standardının dediği gibi) verilen PWDadın ., sistem çağrısı izlemesiyle görülebileceği gibi, adla aynı şeyi verdiğini kontrol edin :
% 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, boyut = 2, blksize) = 131072)) = 0 (0x0)
/ Usr / home / JdeBP / b
% (cd b; PWD = / usr / yerel / etc truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ usr / local / etc" , {mode = drwxr-xr-x, inode = 14835, size = 158, blksize = 10240}) = 0 (0x0)
stat (".", {mode = drwxr-xr-x, inode = 120932, boyut = 2 , blksize = 131072}) = 0 (0x0)
__getcwd ("/ usr / home / JdeBP / a", 1024) = 0 (0x0)
/ Usr / home / JdeBP / a
% (cd b; PWD = / merhaba / truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ hello / there", 0x7fffffffe730) ERR # 2 'Böyle bir dosya veya dizin yok'
__getcwd ("/ usr / home / JdeBP / a", 1024) = 0 (0x0)
/ Usr / home / JdeBP / a
% (cd b; PWD = / usr / ana sayfa / JdeBP / c makas / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ usr / home / JdeBP / c ", {mod = drwxr-xr-x, inode = 120932, boyut = 2, blksize = 131072}) = 0 (0x0)
stat (". ", {Mode = drwxr-xr-x, inode = 120932 , size = 2, blksize = 131072}) = 0 (0x0)
/ Usr / home / JdeBP / c
%
Gördüğünüz gibi: yalnızca getcwd()bir uyuşmazlık tespit ederse çağırır ; ve PWDaslında aynı dizini adlandıran bir dize ayarlayarak , ancak farklı bir yolla kandırılabilir .
getcwd()Kütüphane işlevi kendi başına bir konudur. Ancak précis için:
Gezinmek ..yine kendi başına bir konudur. Başka bir yöntem: Dizinler geleneksel olarak (her ne kadar önceden belirtilmiş olsa da, zorunlu değildir ), her ne kadar ..diskteki dizin veri yapısında bir gerçek içeriyorsa da , çekirdek her dizinin vnode'sinin ana dizinini izler ve böylece ..herhangi bir dizinin içine gidebilir. çalışma dizini. Bu, bu cevabın kapsamı dışında olan bağlama noktası ve değişen kök mekanizmaları tarafından biraz karmaşıktır.
bir kenara
Windows NT aslında benzer bir şey yapar. SetCurrentDirectory()API çağrısı tarafından ayarlanan ve işlem başına çekirdeğin bu dizine (dahili) bir açık dosya tanıtıcısı aracılığıyla izlenen işlem başına tek bir çalışma dizini vardır; ve Win32 programlarının (yalnızca komut yorumlayıcıları değil, tüm Win32 programlarını da içeren) birden fazla çalışma dizininin (sürücü başına bir tane) isimlerini takip etmek için kullandıkları, her değiştirdiklerinde dizine ekleyen veya üzerine yazdıkları bir ortam değişkenleri kümesi vardır .
Geleneksel olarak, Unix ve Linux işletim sistemlerinde olduğu gibi, Win32 programları bu ortam değişkenlerini kullanıcılara göstermez. Bazen bunları Windows NT üzerinde çalışan Unix benzeri alt sistemlerde de görebilir, ancak komut yorumlayıcıların SETkomutlarını belirli bir şekilde kullanarak.
daha fazla okuma