Supposons que je me connecte à un shell sur un système Unix et que je commence à taper des commandes. Je commence d'abord dans le répertoire personnel de mon utilisateur ~
. Je pourrais partir de là cd
vers le répertoire Documents
.
La commande pour modifier le répertoire de travail ici est très simple à comprendre intuitivement: le nœud parent a une liste de nœuds enfants auxquels il peut accéder, et il utilise probablement une variante (optimisée) d'une recherche pour localiser l'existence d'un nœud enfant avec le nommez l'utilisateur entré, et le répertoire de travail est alors "modifié" pour correspondre à cela - corrigez-moi si je me trompe. Il peut même être plus simple que le shell essaie simplement "naïvement" d'essayer d'accéder au répertoire exactement selon les souhaits de l'utilisateur et lorsque le système de fichiers renvoie un certain type d'erreur, le shell affiche une réponse en conséquence.
Ce qui m'intéresse cependant, c'est comment fonctionne le même processus lorsque je navigue dans un répertoire, c'est-à-dire vers un parent ou le parent d'un parent.
Étant donné mon emplacement inconnu, vraisemblablement «aveugle» de Documents
, l'un des nombreux répertoires de l'arborescence du système de fichiers portant ce nom, comment Unix détermine-t-il où je dois être placé ensuite? Fait-il référence à cela pwd
et l'examine-t-il? Si oui, comment suit pwd
-il l'état de navigation actuel?
la source
Réponses:
Les autres réponses sont des simplifications excessives, chacune ne présentant que des parties de l'histoire, et elles sont erronées sur quelques points.
Il existe deux façons de suivre le répertoire de travail:
chdir()
etfchdir()
, la seconde parchroot()
. On peut les voir indirectement dans/proc
sur les systèmes d'exploitation Linux ou via lafstat
commande sur FreeBSD et similaires:Lorsque la résolution de chemin d'accès fonctionne, elle commence à l'un ou l'autre de ces vnodes référencés, selon que le chemin est relatif ou absolu. (Il existe une famille d'
…at()
appels système qui permettent à la résolution de chemin d'accès de commencer au niveau du vnode référencé par un descripteur de fichier ouvert (répertoire) comme troisième option.)Dans les micro-noyaux, la structure des données se trouve dans l'espace d'application, mais le principe de la tenue de références ouvertes à ces répertoires reste le même.
chdir()
.Si l'on change pour un chemin d'accès relatif, il manipule la chaîne pour ajouter ce nom. Si l'on passe à un nom de chemin absolu, il remplace la chaîne par le nouveau nom. Dans les deux cas, il ajuste la chaîne à supprimer
.
et les..
composants et à chasser les liens symboliques en les remplaçant par leurs noms liés. ( Voici le code du shell Z pour cela , par exemple.)Le nom dans la variable de chaîne interne est suivi par une variable shell nommée
PWD
(oucwd
dans les shells C). Ceci est traditionnellement exporté en tant que variable d'environnement (nomméePWD
) vers des programmes générés par le shell.Ces deux méthodes de choses de suivi sont révélées par les
-P
et-L
options à lacd
etpwd
shell commandes intégrées, et par les différences entre les coquilles intégréespwd
commandes et à la fois la/bin/pwd
commande et le haut-pwd
commandes des choses comme (entre autres) VIM et NeoVIM.Comme vous pouvez le voir: obtenir le répertoire de travail "logique" consiste à regarder la
PWD
variable shell (ou la variable d'environnement si l'on n'est pas le programme shell); tandis que l'obtention du répertoire de travail "physique" consiste à appeler lagetcwd()
fonction de bibliothèque.Le fonctionnement du
/bin/pwd
programme lorsque l'-L
option est utilisée est quelque peu subtil. Il ne peut pas faire confiance à la valeur de laPWD
variable d'environnement dont il a hérité. Après tout, il n'a pas besoin d'être invoqué par un shell et les programmes intermédiaires peuvent ne pas avoir implémenté le mécanisme du shell pour que laPWD
variable d'environnement suive toujours le nom du répertoire de travail. Ou quelqu'un peut faire ce que j'ai fait juste là.Donc, ce qu'il fait est (comme le dit la norme POSIX) de vérifier que le nom donné en
PWD
donne la même chose que le nom.
, comme on peut le voir avec une trace d'appel système:Comme vous pouvez le voir: il n'appelle que
getcwd()
s'il détecte un décalage; et il peut être trompé en définissantPWD
une chaîne qui nomme effectivement le même répertoire, mais par une route différente.La
getcwd()
fonction de bibliothèque est un sujet à part entière. Mais pour précis:..
répertoire. Il s'est arrêté lorsqu'il a atteint une boucle où..
était le même que son répertoire de travail ou lorsqu'une erreur s'est produite lors de l'ouverture du suivant..
. Ce serait beaucoup d'appels système sous les couvertures.Cependant, notez que même sur FreeBSD et ces autres systèmes d'exploitation, le noyau ne garde pas la trace du répertoire de travail avec une chaîne.
Naviguer vers
..
est à nouveau un sujet à part entière. Un autre précis: Bien que les répertoires conventionnellement (bien que, comme cela a déjà été mentionné, cela ne soit pas requis) contiennent un réel..
dans la structure de données du répertoire sur le disque, le noyau suit le répertoire parent de chaque répertoire vnode lui-même et peut ainsi naviguer vers le..
vnode de n'importe quel directeur de travail. Ceci est quelque peu compliqué par le point de montage et les mécanismes racine modifiés, qui dépassent le cadre de cette réponse.De côté
Windows NT fait en fait une chose similaire. Il existe un seul répertoire de travail par processus, défini par l'
SetCurrentDirectory()
appel d'API et suivi par processus par le noyau via un descripteur de fichier ouvert (interne) vers ce répertoire; et il existe un ensemble de variables d'environnement que les programmes Win32 (pas seulement les interpréteurs de commandes, mais tous les programmes Win32) utilisent pour suivre les noms de plusieurs répertoires de travail (un par lecteur), en les ajoutant ou en les écrasant chaque fois qu'ils changent de répertoire.Classiquement, contrairement au cas des systèmes d'exploitation Unix et Linux, les programmes Win32 n'affiche pas ces variables d'environnement pour les utilisateurs. On peut parfois les voir dans des sous-systèmes de type Unix fonctionnant sous Windows NT, ainsi qu'en utilisant les commandes des interprètes de
SET
commande d'une manière particulière.Lectures complémentaires
pwd
" . The Open Group Base Spécifications Issue 7. IEEE 1003.1: 2008. Le groupe ouvert. 2016.la source
..
dans le contexte de Plan9,.
et les..
composants et à chasser les liens symboliques en les remplaçant par leurs noms liés. … Le nom dans la variable de chaîne interne est suivi par une variable shell nomméePWD
… ”(soulignement ajouté). … (Suite)PWD
=…/b
après unecd b
commande, même s'ilb
s'agit d'un lien symbolique versa
- donc le shell ne «poursuit» pas lea -> b
lien. Avez-vous déformé ou ai-je mal lu?CHASE_LINKS
.Le noyau ne garde pas trace des noms de répertoires ou de fichiers; un fichier ou un répertoire est représenté dans le noyau par une paire inode / périphérique. Les appels système comme
chdir()
,open()
, etc. prennent un chemin en tant que paramètre, qui peut être absolue (par exemple/etc/passwd
), ou par rapport au répertoire courant (exemples:Documents
,..
). Lorsqu'un processus s'exécutechdir("Documents")
, une recherche est effectuéeDocuments
dans le répertoire de travail actuel et le répertoire de travail du processus est mis à jour pour faire référence à ce répertoire. Du point de vue du noyau, il n'y a rien de spécial dans le nom "..", c'est juste une convention dans le système de fichiers qui..
fait référence au répertoire parent.La
getcwd()
fonction n'est pas un appel système, mais une fonction de bibliothèque qui doit remonter jusqu'au répertoire racine, en enregistrant les noms des composants du chemin sur le chemin.la source
Fait intéressant, la tradition
cd ..
est beaucoup plus simple quepwd
. Les répertoires nommés..
sont placés explicitement dans le système de fichiers. Le système garde la trace du périphérique / inode du répertoire courant, donccd ..
ou plus précisément l'appel systèmechdir("..")
implique simplement de rechercher le nom ".." dans le fichier appartenant à l'inode du répertoire actuel et de changer le périphérique / inode du répertoire actuel en valeur trouvée là-bas.pwd
(plus précisément/bin/pwd
) suit les..
liens successivement et lit les répertoires respectifs jusqu'à trouver l'inode d'où il vient, assemblant la liste de ces noms à l'envers jusqu'à ce qu'il atteigne le répertoire racine (notamment ne contenant pas d'..
entrée).Maintenant, c'est le comportement de base de bas niveau d'origine. Les commandes shell réelles
pwd
reposent plutôt sur une variété de techniques de mise en cache du nom de chemin actuel. Mais au fond, ce n'est que son inode qui est réellement connu. Cela implique qu'une fois les liens symboliques utilisés pour naviguer dans les répertoires, les notions de nom de répertoire de travail actuel du shell actuel et du système/bin/pwd
peuvent diverger.la source