web-dev-qa-db-fra.com

Pourquoi les liens physiques vers des répertoires ne sont-ils pas autorisés sous UNIX / Linux?

J'ai lu dans des manuels que Unix/Linux n'autorise pas les liens physiques vers les répertoires mais autorise les liens logiciels. Est-ce parce que, lorsque nous avons des cycles et si nous créons des liens durs, et après un certain temps, nous supprimons le fichier d'origine, cela pointera vers une valeur de poubelle?

Si les cycles étaient la seule raison de ne pas autoriser les liens physiques, alors pourquoi les liens logiciels vers les répertoires sont-ils autorisés?

131
user3539

C'est juste une mauvaise idée, car il n'y a aucun moyen de faire la différence entre un lien dur et un nom d'origine.

Autoriser les liens physiques vers les répertoires briserait la structure graphique acyclique dirigée du système de fichiers, créant éventuellement des boucles de répertoires et des sous-arborescences de répertoires, ce qui rendrait fsck et toute autre arborescence de fichiers sujets aux erreurs.

Tout d'abord, pour comprendre cela, parlons des inodes. Les données du système de fichiers sont conservées dans des blocs sur le disque, et ces blocs sont collectés ensemble par un inode. Vous pouvez considérer l'inode comme LE fichier. Les inodes manquent cependant de noms de fichiers. C'est là que les liens entrent en jeu.

Un lien n'est qu'un pointeur vers un inode. Un répertoire est un inode qui contient des liens. Chaque nom de fichier dans un répertoire n'est qu'un lien vers un inode. L'ouverture d'un fichier sous Unix crée également un lien, mais c'est un type de lien différent (ce n'est pas un lien nommé).

Un lien dur n'est qu'une entrée de répertoire supplémentaire pointant vers cet inode. Quand vous ls -l, le nombre après les autorisations est le nombre de liens nommé. La plupart des fichiers normaux auront un lien. La création d'un nouveau lien dur vers un fichier fera pointer les deux noms de fichiers vers le même inode. Remarque:

% ls -l test
ls: test: No such file or directory
% touch test
% ls -l test
-rw-r--r--  1 danny  staff  0 Oct 13 17:58 test
% ln test test2
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
% touch test3
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
-rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3
            ^
            ^ this is the link count

Maintenant, vous pouvez clairement voir qu'il n'existe pas de lien dur. Un lien dur est identique à un nom normal. Dans l'exemple ci-dessus, test ou test2, quel est le fichier d'origine et quel est le lien dur? À la fin, vous ne pouvez pas vraiment le dire (même par des horodatages) car les deux noms pointent vers le même contenu, le même inode:

% ls -li test*  
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
14445892 -rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3

Le -i flag à ls vous montre les numéros d'inode au début de la ligne. Notez comment test et test2 ont le même numéro d'inode, mais test3 en a un autre.

Maintenant, si vous étiez autorisé à le faire pour les répertoires, deux répertoires différents à différents points du système de fichiers pourraient pointer vers la même chose. En fait, un sous-répertoire pourrait renvoyer à son grand-parent, créant une boucle.

Pourquoi cette boucle est-elle une préoccupation? Parce que lorsque vous traversez, il n'y a aucun moyen de détecter que vous bouclez (sans garder une trace des numéros d'inode pendant que vous traversez). Imaginez que vous écrivez la commande du, qui doit parcourir les sous-répertoires pour découvrir l'utilisation du disque. Comment du pourrait-il savoir quand il a frappé une boucle? C'est une tâche sujette aux erreurs et beaucoup de comptabilité que du devrait faire, juste pour réaliser cette tâche simple.

Les liens symboliques sont une toute autre bête, en ce qu'ils sont un type spécial de "fichier" que de nombreuses API de système de fichiers ont tendance à suivre automatiquement. Remarque: un lien symbolique peut pointer vers une destination inexistante, car il pointe par son nom et non directement vers un inode. Ce concept n'a pas de sens avec les liens durs, car la simple existence d'un "lien dur" signifie que le fichier existe.

Alors pourquoi du peut-il gérer facilement les liens symboliques et non les liens physiques? Nous avons pu voir ci-dessus que les liens physiques ne se distinguent pas des entrées de répertoire normales. Cependant, les liens symboliques sont spéciaux, détectables et désactivables! du remarque que le lien symbolique est un lien symbolique et l'ignore complètement!

% ls -l 
total 4
drwxr-xr-x  3 danny  staff  102 Oct 13 18:14 test1/
lrwxr-xr-x  1 danny  staff    5 Oct 13 18:13 test2@ -> test1
% du -ah
242M    ./test1/bigfile
242M    ./test1
4.0K    ./test2
242M    .
144
Danny Dulai

À l'exception des points de montage, chaque répertoire a un seul et unique parent: ...

Une façon de faire pwd est de vérifier le périphérique: inode pour '.' et '..'. S'ils sont identiques, vous avez atteint la racine du système de fichiers. Sinon, trouvez le nom du répertoire courant dans le parent, poussez-le sur une pile et commencez à comparer '../.' avec '../ ..', puis '../../.' avec '../../ ..', etc. Une fois que vous avez atteint la racine, commencez à sauter et à imprimer les noms de la pile. Cet algorithme repose sur le fait que chaque répertoire a un et un seul parent.

Si les liens physiques vers les répertoires étaient autorisés, vers lequel des parents multiples .. Devrait-il pointer? C'est une raison impérieuse pour laquelle les liens physiques vers des répertoires ne sont pas autorisés.

Les liens symboliques vers les répertoires ne causent pas ce problème. Si un programme le souhaite, il pourrait faire une lstat() sur chaque partie du chemin et détecter lorsqu'un lien symbolique est rencontré. L'algorithme pwd renverra le vrai chemin absolu pour un répertoire cible. Le fait qu'il y ait un morceau de texte quelque part (le lien symbolique) qui pointe vers le répertoire cible est à peu près sans importance. L'existence d'un tel lien symbolique ne crée pas de boucle dans le graphique.

14
Joe Inwap

Vous pouvez utiliser bind mount pour simuler des répertoires de liaison matériels

Sudo mount --bind /some/existing_real_contents /else/dummy_but_existing_directory
Sudo umount /else/dummy_but_existing_directory
13
zainengineer

Je voudrais ajouter quelques points supplémentaires sur cette question. Les liens physiques pour les répertoires sont autorisés sous Linux, mais de manière restreinte.

Une façon de tester cela est lorsque nous listons le contenu d'un répertoire, nous trouvons deux répertoires spéciaux "." et "..". Comme nous le savons "." pointe vers le même répertoire et ".." pointe vers le répertoire parent.

Permet donc de créer une arborescence de répertoires où "a" est le répertoire parent qui a le répertoire "b" comme enfant.

 a
 `-- b

Notez l'inode du répertoire "a". Et quand on fait un ls -la du répertoire "a" nous pouvons voir que "." répertoire pointe également vers le même inode.

797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 a

Et ici, nous pouvons constater que le répertoire "a" a trois liens durs. Cela est dû au fait que l'inode 797358 possède trois liens physiques au nom de "." à l'intérieur du répertoire "a" et nommez ".." à l'intérieur du répertoire "b" et un avec le nom "a" lui-même.

$ ls -ALi a/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 .

$ ls -ALi a/b/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 ..

Nous pouvons donc comprendre ici que les liens physiques sont là pour que les répertoires se connectent uniquement à leurs répertoires parent et enfant. Et donc un répertoire sans enfant n'aura que 2 hardlink, et donc le répertoire "b" n'aura que deux hardlink.

Une des raisons pour lesquelles la liaison dure de répertoires a été librement empêchée serait d'éviter les boucles de référence infinies qui confondraient les programmes qui traversent le système de fichiers.

Comme le système de fichiers est organisé en arbre et que l'arbre ne peut pas avoir de référence cyclique, cela aurait dû être évité.

7
Kannan Mohan

Aucun des éléments suivants n'est la véritable raison pour interdire les liens durs vers les répertoires; chaque problème est assez facile à résoudre:

  • les cycles de la structure arborescente provoquent une traversée difficile
  • plusieurs parents, alors quel est le "vrai"?
  • garbage collection du système de fichiers

Le raison réelle (comme l'indique @ Thorbjørn Ravn Andersen) survient lorsque vous supprimez un répertoire qui a plusieurs parents, du répertoire indiqué par ..:

Qu'est-ce que doit .. pointez maintenant sur?

Si le répertoire est supprimé de son parent mais que son nombre de liens est toujours supérieur à 0 alors il doit y avoir quelque chose, quelque part le montrant encore. Vous ne pouvez pas quitter .. ne montrant rien; de nombreux programmes reposent sur .., de sorte que le système devrait parcourir l'ensemble du système de fichiers jusqu'à ce qu'il trouve la première chose qui pointe vers le répertoire supprimé, juste pour mettre à jour ... Soit cela, soit le système de fichiers devrait conserver une liste de tous les répertoires pointant vers un répertoire lié en dur.

Dans les deux cas, il s'agirait d'un surcharge de performances et d'un complication supplémentaire pour les métadonnées et/ou le code du système de fichiers, de sorte que les concepteurs ont décidé de ne pas l'autoriser.

6
Lqueryvg

La création de liens physiques sur les répertoires serait irréversible. Supposons que nous ayons:

/dir1
├──this.txt
├──directory
│  └──subfiles
└──etc

Je le relie à /dir2.

Donc /dir2 contient désormais tous ces fichiers et répertoires

Et si je change d'idée? Je ne peux pas simplement rmdir /dir2 (car il n'est pas vide)

Et si je supprime récursivement dans /dir2... il sera supprimé de /dir1 aussi!

À mon humble avis, c'est une raison largement suffisante pour éviter cela!

Modifier:

Les commentaires suggèrent de supprimer le répertoire en faisant rm dessus. Mais rm sur un répertoire non vide échoue et ce comportement doit rester, que le répertoire soit lié ou non. Vous ne pouvez donc pas simplement rm le dissocier. Il faudrait un nouvel argument à rm, juste pour dire "si l'inode du répertoire a un nombre de références> 1, alors dissociez uniquement le répertoire".

Ce qui, à son tour, brise un autre principe de moindre surprise: cela signifie que la suppression d'un lien physique de répertoire que je viens de créer n'est pas la même chose que la suppression d'un lien physique de fichier normal ...

Je reformulerai ma phrase: Sans développement supplémentaire, la création de liens physiques ne serait pas réversible (car aucune commande actuelle ne pourrait gérer la suppression sans être incohérente avec le comportement actuel)

Si nous permettons à plus de développement de gérer le cas, le nombre d’écueils et le risque de perte de données si vous n’êtes pas suffisamment au courant du fonctionnement du système, un tel développement implique, IMHO est-il suffisant raison de restreindre le hardlinking sur les répertoires.

4

Ceci est une bonne explication. Concernant "Lequel des multiples parents devrait .. pointer du doigt?" une solution serait qu'un processus conserve son chemin wd complet, soit sous forme d'inodes, soit sous forme de chaîne. les inodes seraient plus robustes car les noms peuvent être modifiés. Au moins dans l'ancien temps, il y avait un inode in-core pour chaque fichier ouvert qui était incrémenté chaque fois qu'un fichier était ouvert, décrémenté à la fermeture. Quand il atteindrait zéro, le stockage pointé serait libéré. Lorsque le fichier n'était plus ouvert par personne, il (la copie in-core) était abandonné. Cela conserverait le chemin d'accès valide si un autre processus déplaçait un répertoire vers un autre répertoire alors que le sous-répertoire se trouvait dans le chemin d'un autre processus. Similaire à la façon dont vous pouvez supprimer un fichier ouvert, mais il est simplement supprimé du répertoire, mais toujours ouvert pour tous les processus qui l'ont ouvert.

Les répertoires de liaison physique étaient auparavant librement autorisés dans Bell Labs UNIX, au moins V6 et V7, Je ne sais pas pour Berkeley ou une version ultérieure. Aucun drapeau requis. Pourriez-vous faire des boucles? Oui, ne fais pas ça. Il est très clair ce que vous faites si vous faites une boucle. Nether devrait vous pratiquer à nouer autour de votre cou pendant que vous attendez votre tour pour sauter en parachute hors d'un avion si vous avez l'autre extrémité accrochée à un crochet sur la cloison.

Ce que JE espérais en faire aujourd'hui était de lier durement lhome à la maison afin que je puisse avoir/home/administ disponible, que/home soit couvert ou non avec une sortie automatique sur la maison, cette monture automatique ayant un lien symbolique nommé administ vers/lhome/administ. Cela me permet d'avoir un compte administratif qui fonctionne quel que soit l'état de mon système de fichiers principal. Ceci EST une expérience pour linux, mais je pense avoir appris à un moment donné pour le SunOS basé sur UCB que les montages automatiques sont effectués au niveau de la chaîne ascii. Il est difficile de voir comment cela pourrait être fait autrement en tant que couche au-dessus de tout FS arbitraire.

J'ai lu ailleurs cela. et .. ne sont plus des fichiers dans le répertoire. Je suis sûr qu'il y a de bonnes raisons à tout cela, et qu'une grande partie de ce que nous apprécions (comme pouvoir monter NTFS) est possible à cause de telles choses, mais une partie de l'élégance d'UNIX était dans l'implémentation. Ce sont les avantages tels que la généralité et la malléabilité que cette élégance a fournis qui lui ont permis d'être si robustes et de durer pendant quatre décennies. Comme nous perdons les implémentations élégantes, cela deviendra finalement comme Windows (j'espère que je me trompe!). Quelqu'un créerait alors un nouvel OS basé sur des principes élégants. Quelque chose à quoi penser. Peut-être que je me trompe, je ne suis pas (évidemment) familier avec la mise en œuvre actuelle. Il est étonnant bien que la compréhension de 30 ans soit applicable à Linux ... la plupart du temps!

1
user57607

D'après ce que je comprends, la principale raison est qu'il est utile de pouvoir changer les noms de répertoire sans gâcher les programmes en cours d'exécution qui utilisent leur répertoire de travail pour référencer d'autres fichiers. Supposons que vous utilisiez Wine pour exécuter ~/.newwineprefix/drive_c/Program Files/Firefox/Firefox.exe, et vous vouliez déplacer le préfixe entier vers ~/.wine au lieu. Si pour une raison étrange, Firefox accédait à drive_c/windows en faisant référence à ../../windows, renommant ~/.newwineprefix interrompt les implémentations de .. qui garde la trace du répertoire parent sous forme de chaîne de texte au lieu d'un inode.

Le stockage de l'inode d'un répertoire parent unique doit être plus simple que d'essayer de garder une trace de chaque chemin d'accès à la fois comme une chaîne de texte et une série d'inodes.

Une autre raison est que les applications qui se comportent mal peuvent être capables de créer des boucles. Les applications qui se comportent devraient pouvoir vérifier si l'inode du répertoire déplacé est le même que l'inode de l'un des répertoires imbriqués dans lesquels il est déplacé, tout comme vous ne pouvez pas déplacer un répertoire en lui-même, mais cela pourrait ne pas être appliqué. au niveau du système de fichiers.

Encore une autre raison pourrait être que si vous pouviez créer des liens physiques avec des répertoires, vous voudriez éviter de lier en dur un répertoire que vous ne pouviez pas modifier. find a des considérations de sécurité car il est utilisé pour effacer les fichiers créés par d'autres utilisateurs à partir de répertoires temporaires, ce qui peut provoquer des problèmes si un utilisateur change de répertoire réel pour un lien symbolique pendant que find appelle une autre commande. La possibilité de lier en dur des répertoires importants obligerait un administrateur à ajouter des tests supplémentaires à find pour éviter de les affecter. (Ok, vous ne pouvez déjà pas le faire pour les fichiers, donc cette raison n'est pas valide.)

Une autre raison encore est que le stockage de l'inode du répertoire parent peut fournir une redondance supplémentaire en cas de corruption ou d'endommagement du système de fichiers. Si vous vouliez .. pour répertorier tous les répertoires parents qui contiennent un lien physique vers celui-ci, afin qu'un parent différent et arbitraire puisse être facilement trouvé si le répertoire actuel est dissocié, non seulement vous violez l'idée que les liens physiques sont égaux, vous devez changer la façon dont le fichier le système stocke et utilise des inodes. Faire en sorte que les programmes traitent les chemins comme une série (unique à chaque lien dur) d'inodes de répertoire éviterait cela, mais vous n'obtiendrez pas la redondance en cas de dommages au système de fichiers.

0
Misaki