Angenommen, ich melde mich in einer Shell auf einem Unix-System an und beginne, Befehle abzuklopfen. Ich beginne zunächst im Home-Verzeichnis meines Benutzers ~
. Ich könnte von dort cd
runter ins Telefonbuch Documents
.
Der Befehl zum Ändern des Arbeitsverzeichnisses ist hier sehr einfach und intuitiv zu verstehen: Der übergeordnete Knoten verfügt über eine Liste von untergeordneten Knoten, auf die er zugreifen kann, und verwendet vermutlich eine (optimierte) Variante einer Suche, um die Existenz eines untergeordneten Knotens mit der zu lokalisieren Name des Benutzers eingegeben, und das Arbeitsverzeichnis wird dann "geändert", um dies zu entsprechen - korrigieren Sie mich, wenn ich mich dort irre. Es kann sogar einfacher sein, dass die Shell einfach "naiv" versucht, genau nach den Wünschen des Benutzers auf das Verzeichnis zuzugreifen. Wenn das Dateisystem eine Art Fehler zurückgibt, zeigt die Shell eine entsprechende Antwort an.
Was mich jedoch interessiert, ist, wie der gleiche Prozess funktioniert, wenn ich in einem Verzeichnis navigiere, dh zu einem Elternteil oder einem Elternteil.
Documents
Wie bestimmt Unix angesichts meines unbekannten, vermutlich "blinden" Standorts eines von möglicherweise vielen Verzeichnissen im gesamten Dateisystembaum mit diesem Namen, wo ich als nächstes platziert werden soll? Wird darauf Bezug genommen pwd
und geprüft? Wenn ja, wie wird pwd
der aktuelle Navigationsstatus verfolgt?
quelle
Antworten:
Die anderen Antworten sind Übervereinfachungen, die jeweils nur Teile der Geschichte darstellen und in einigen Punkten falsch sind.
Es gibt zwei Möglichkeiten, um das Arbeitsverzeichnis zu verfolgen:
chdir()
und diefchdir()
Systemaufrufe, wobei letztere durchchroot()
. Man kann sie indirekt/proc
unter Linux-Betriebssystemen oder über denfstat
Befehl unter FreeBSD und dergleichen sehen:Wenn die Pfadnamenauflösung ausgeführt wird, beginnt sie bei dem einen oder anderen dieser referenzierten Knoten, je nachdem, ob der Pfad relativ oder absolut ist. (Es gibt eine
…at()
Reihe von Systemaufrufen, mit denen die Pfadnamenauflösung an dem Knoten beginnen kann, auf den ein offener (Verzeichnis-) Dateideskriptor als dritte Option verweist.)In Microkernel Unices befindet sich die Datenstruktur im Anwendungsbereich, aber das Prinzip, Verweise auf diese Verzeichnisse offen zu halten, bleibt dasselbe.
chdir()
.Wenn ein relativer Pfadname geändert wird, wird die Zeichenfolge bearbeitet, um diesen Namen anzufügen. Wenn ein absoluter Pfadname geändert wird, wird die Zeichenfolge durch den neuen Namen ersetzt. In beiden Fällen wird die Zeichenfolge angepasst, um Komponenten zu entfernen
.
und..
symbolische Verknüpfungen aufzuspüren, indem sie durch ihre verknüpften Namen ersetzt werden. ( Hier ist zum Beispiel der Code der Z-Shell .)Der Name in der internen Zeichenfolgenvariablen wird von einer Shell-Variablen namens
PWD
(odercwd
in den C-Shells) verfolgt. Dies wird herkömmlicherweise als Umgebungsvariable (benanntPWD
) in Programme exportiert, die von der Shell erzeugt werden.Diese beiden Methoden der Verfolgung Dinge enthüllt werden von den
-P
und-L
Optionen auf diecd
undpwd
Shell integrierte Befehle, und durch die Unterschiede zwischen den Schalen built-inpwd
Befehle und sowohl den/bin/pwd
Befehl und die eingebaute inpwd
Befehle von Dingen wie (unter anderem) VIM und NeoVIM.Wie Sie sehen können: Um das "logische" Arbeitsverzeichnis zu erhalten, müssen Sie sich die
PWD
Shell-Variable (oder die Umgebungsvariable, falls es sich nicht um das Shell-Programm handelt) ansehen. Um das "physische" Arbeitsverzeichnis zu erhalten, muss diegetcwd()
Bibliotheksfunktion aufgerufen werden.Die Bedienung des
/bin/pwd
Programms bei Verwendung der-L
Option ist etwas subtil. Es kann dem Wert derPWD
Umgebungsvariablen, die es geerbt hat, nicht vertrauen . Schließlich muss es nicht von einer Shell aufgerufen worden sein, und möglicherweise haben intervenierende Programme den Mechanismus der Shell, mit dem diePWD
Umgebungsvariable immer den Namen des Arbeitsverzeichnisses verfolgt, nicht implementiert . Oder jemand kann das tun, was ich gerade dort getan habe.Es wird also (wie der POSIX-Standard sagt) überprüft, ob der in angegebene Name
PWD
das Gleiche ergibt wie der Name.
, wie bei einem Systemaufruf-Trace zu sehen ist:Wie Sie sehen können: Es ruft nur auf,
getcwd()
wenn es eine Nichtübereinstimmung feststellt. und es kann getäuscht werden, indemPWD
eine Zeichenfolge festgelegt wird, die zwar dasselbe Verzeichnis benennt, jedoch auf einem anderen Weg.Die
getcwd()
Bibliotheksfunktion ist ein eigenständiges Fach. Aber vorab:..
nachzuschlagen. Es wurde angehalten, als es eine Schleife erreichte, in der..
es sich um das Arbeitsverzeichnis handelte, oder wenn ein Fehler beim Öffnen des nächsten Verzeichnisses auftrat..
. Dies wäre eine Menge Systemaufrufe unter der Decke.Beachten Sie jedoch, dass auch auf FreeBSD und die anderen Betriebssysteme der Kernel nicht funktioniert mit einem String - Spur des Arbeitsverzeichnisses halten.
Das Navigieren zu
..
ist wieder ein eigenständiges Thema. Eine weitere Voraussetzung: Obwohl Verzeichnisse herkömmlicherweise (obwohl, wie bereits erwähnt, dies nicht erforderlich ist) eine tatsächliche..
Verzeichnisdatenstruktur auf der..
Festplatte enthalten , verfolgt der Kernel das übergeordnete Verzeichnis jedes Verzeichnisknotens selbst und kann so zum Knoten eines beliebigen Verzeichnisknotens navigieren Arbeitsverzeichnis. Dies wird durch den Einhängepunkt und geänderte Root-Mechanismen etwas kompliziert, die den Rahmen dieser Antwort sprengen.Beiseite
Windows NT macht in der Tat eine ähnliche Sache. Es gibt ein einziges Arbeitsverzeichnis pro Prozess, das vom
SetCurrentDirectory()
API-Aufruf festgelegt und vom Kernel über ein (internes) offenes Dateihandle zu diesem Verzeichnis pro Prozess verfolgt wird. Außerdem gibt es eine Reihe von Umgebungsvariablen, mit denen Win32-Programme (nicht nur die Befehlsinterpreter, sondern alle Win32-Programme) die Namen mehrerer Arbeitsverzeichnisse (eines pro Laufwerk) verfolgen und diese bei jedem Verzeichniswechsel anhängen oder überschreiben.Im Gegensatz zu Unix- und Linux-Betriebssystemen zeigen Win32-Programme Benutzern diese Umgebungsvariablen normalerweise nicht an. Man kann sie jedoch manchmal in Unix-ähnlichen Subsystemen sehen, die unter Windows NT ausgeführt werden, oder indem man die
SET
Befehle der Befehlsinterpreter auf eine bestimmte Weise verwendet.Weitere Lektüre
pwd
" . The Open Group Base Specifications Issue 7. IEEE 1003.1: 2008. Die offene Gruppe. 2016.quelle
..
im Zusammenhang mit Plan9,.
und symbolische Verknüpfungen aufzuspüren, indem sie durch ihre verknüpften Namen ersetzt werden. … Der Name in der internen Zeichenfolgenvariablen wird von einer Shell-Variablen mit dem Namen … “(Hervorhebung hinzugefügt) verfolgt. … (Fortsetzung)..
PWD
PWD
=…/b
nach einemcd b
Befehl, obwohlb
es sich um eine symbolische Verknüpfung handelta
- damit die Shell diea -> b
Verknüpfung nicht „jagt“ . Haben Sie falsch angegeben oder habe ich falsch gelesen?CHASE_LINKS
.Der Kernel verfolgt weder Verzeichnis- noch Dateinamen. Eine Datei oder ein Verzeichnis wird im Kernel durch ein Inode / Device-Paar dargestellt. Systemaufrufe wie
chdir()
,open()
etc. nehmen einen Pfad als Parameter, die absoluten sein kann ( zum Beispiel/etc/passwd
) oder relativ zum aktuellen Verzeichnis (Beispiele:Documents
,..
). Wenn ein Prozess ausgeführt wirdchdir("Documents")
, wirdDocuments
im aktuellen Arbeitsverzeichnis nachgeschlagen, und das Arbeitsverzeichnis des Prozesses wird aktualisiert, um auf dieses Verzeichnis zu verweisen. Aus der Sicht des Kernels enthält der Name ".." nichts Besonderes. Es handelt sich lediglich um eine Konvention im Dateisystem, die..
auf das übergeordnete Verzeichnis verweist.Die
getcwd()
Funktion ist kein Systemaufruf, sondern eine Bibliotheksfunktion, die sich bis zum Stammverzeichnis durcharbeiten muss und dabei die Namen der Pfadkomponenten aufzeichnet.quelle
Interessanterweise ist traditionell
cd ..
viel viel einfacher alspwd
. Die genannten Verzeichnisse..
werden explizit im Dateisystem abgelegt. Das System verfolgt das Gerät / den Inode des aktuellen Verzeichnisses, sodasscd ..
der Systemaufrufchdir("..")
genau genommen nur das Nachschlagen des Namens ".." in der Datei zum Inode des aktuellen Verzeichnisses und das Ändern des Geräts / des Inodes des aktuellen Verzeichnisses in "." Wert dort gefunden.pwd
(genauer/bin/pwd
) folgt den..
Links nacheinander und liest die entsprechenden Verzeichnisse, bis der Inode gefunden ist, von dem sie stammen. Die Liste dieser Namen wird umgekehrt zusammengestellt, bis das Stammverzeichnis erreicht ist (insbesondere kein..
Eintrag enthalten ist).Dies ist das ursprüngliche Grundverhalten auf niedriger Ebene. Tatsächliche Shell-Befehle
pwd
stützen sich stattdessen auf eine Vielzahl von Techniken, mit denen der aktuelle Pfadname zwischengespeichert wird. Im Kern ist jedoch nur die Inode bekannt. Dies bedeutet, dass, sobald Symlinks zum Navigieren in Verzeichnissen verwendet werden, die aktuellen Bezeichnungen der Arbeitsverzeichnisnamen der aktuellen Shell und des Systems/bin/pwd
möglicherweise abweichen.quelle