Unix / Linuxはディレクトリへのハードリンクを許可しないが、ソフトリンクは許可することを教科書で読みました。それは、サイクルがあり、ハードリンクを作成し、しばらくして元のファイルを削除すると、ガベージ値が示されますか?
ハードリンクを許可しない理由がサイクルだけだった場合、ディレクトリへのソフトリンクはなぜですか?許可されますか?
コメント
cwdであり、..
の使用を確認したときに参照します。もちろん、それはシンボリックリンクがそれを念頭に置いて作成される必要があることを意味しますが、シンボリックリンクを壊さないようにすでに注意する必要があり、追加のルールがそうなるとは思いません’それらを役に立たなくします。
回答
これは悪い考えです。ハードリンクと元の名前の違いを区別する方法はありません。
ディレクトリへのハードリンクを許可すると、ファイルシステムの有向非巡回グラフ構造が壊れ、ディレクトリループが作成され、ディレクトリサブツリーがぶら下がる可能性があります。 fsck
やその他のファイルツリーウォーカーでエラーが発生しやすくします。
まず、これを理解するために、iノードについて説明します。ファイルシステムのデータは次の場所に保持されます。ディスク上のブロック、およびそれらのブロックはiノードによってまとめられます。iノードはファイルと考えることができます。ただし、iノードにはファイルファイルがありません。そこでリンクが入ります。
リンクはただのリンクです。 iノードへのポインタ。ディレクトリは、リンクを保持するiノードです。ディレクトリ内の各ファイル名は、iノードへの単なるリンクです。 Unixでファイルを開くとリンクも作成されますが、それは別のタイプのリンクです(名前付きリンクではありません)。
ハードリンクは、そのiノードを指す単なる追加のディレクトリエントリです。 ls -l
の場合、権限の後の数字は名前付きリンクの数です。ほとんどの通常のファイルには1つのリンクがあります。ファイルへの新しいハードリンクを作成すると、両方のファイル名が同じiノードを指すようになります。注:
% 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
これで、ハードリンクなどがないことがはっきりとわかります。ハードリンクは通常の名前と同じです。上記の例では、test
またはtest2
で、どちらが元のファイルで、どちらがハードリンクですか?結局のところ、両方の名前が同じ内容、同じiノードを指しているため(タイムスタンプでも)実際にはわかりません。
% 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
iv ls
のid = “0c65772eaa”>
フラグは行頭のiノード番号を示します。test
とtest2
のiノード番号は同じですが、test3
のiノード番号は異なります。
許可されている場合は、ディレクトリに対してこれを行うと、ファイルシステムの異なるポイントにある2つの異なるディレクトリが同じものを指す可能性があります。実際、サブディレクトリはその祖父母を指し示し、ループを作成する可能性があります。
このループが懸念される理由トラバースしているときは、ループしていることを検出する方法がないためです(トラバース時にiノード番号を追跡する必要があります)。du
コマンドを記述していると想像してください。サブディレクトリを繰り返してディスク使用量を確認します。du
はどのようにしてwheを認識しますかnループにぶつかった? du
は、この単純なタスクを実行するためだけに、エラーが発生しやすく、多くの簿記を行う必要があります。
シンボリックリンクは、まったく別の獣です。それらは、多くのファイルファイルシステムAPIが自動的に従う傾向がある特殊なタイプの「ファイル」であること。シンボリックリンクは、iノードを直接指すのではなく、名前で指すため、存在しない宛先を指すことができることに注意してください。 「ハードリンク」が存在するだけでファイルが存在することを意味するため、この概念はハードリンクでは意味がありません。
では、なぜdu
を処理できるのでしょうか。シンボリックリンクは簡単でハードリンクではありませんか?ハードリンクは通常のディレクトリエントリと区別がつかないことがわかりました。ただし、シンボリックリンクは特別で、検出可能で、スキップ可能です。du
は、 symlinkはシンボリックリンクであり、完全にスキップします!
% 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 .
コメント
-
Allowing hard links to directories would break the directed acyclic graph structure of the filesystem
。ハードリンクを使用したサイクルの問題について詳しく説明してください。シンボリックリンクで問題ないのはなぜですか - link()システムコールにサイクル検出を追加し、サイクルを作成する場合はディレクトリハードリンクの作成を拒否することで、Macで許可したようです。 。合理的な解決策のようです。
- @psusi mkdir -p a / b; nocheckln c a; mv c a / b; –nochecklnディレクトリ引数をチェックせず、リンクに渡すだけの理論上のlnがあります。サイクルが作成されないため、’ c
。次に、’ c ‘を’ a / b 、a / b / cからサイクルが作成されます-> a / -link()のチェックインでは不十分です
- サイクルは非常に悪いです。 Windowsには、ハードリンクディレクトリである”ジャンクション”でこの問題があります。プロファイル全体に誤ってアクセス許可を適用すると、無限のサイクルを作成する一連のジャンクションが明らかになります。ディレクトリを再帰的に実行すると、パスの長さの制限によって停止するまで再帰します。
- @WhiteWinterWolfによると、このリンクによると、Time Machineのサポートが特に追加されていますが、rootのみが実行できます。 superuser.com/questions/360926/ …
回答
バインドマウントを使用してハードリンクディレクトリをシミュレートできます
sudo mount --bind /some/existing_real_contents /else/dummy_but_existing_directory sudo umount /else/dummy_but_existing_directory
回答
マウントポイントを除いて、各ディレクトリには唯一の親があります:..
。
への1つの方法pwd
は、device:inodeで「。」をチェックします。および「..」。それらが同じである場合は、ファイルシステムのルートに到達しています。それ以外の場合は、親で現在のディレクトリの名前を見つけ、それをスタックにプッシュして、「../」の比較を開始します。 「../ ..」、次に「../../。」 「../../ ..」などを使用します。「ルートに到達したら、スタックから名前をポップして出力し始めます。このアルゴリズムは、各ディレクトリに1つだけの親があるという事実に依存しています。
ディレクトリへのハードリンクが許可されている場合、複数の親のどれを..
ポイントする必要がありますか?これが、ディレクトリへのハードリンクが許可されない理由の1つです。
ディレクトリへのシンボリックリンクはその問題を引き起こしません。プログラムが必要な場合は、パス名の各部分でlstat()
を実行し、シンボリックリンクが検出されたことを検出できます。 pwd
アルゴリズムは、ターゲットディレクトリの真の絶対パス名を返します。ターゲットディレクトリを指すテキスト(シンボリックリンク)がどこかにあるという事実は、ほとんど関係ありません。このようなシンボリックリンクが存在しても、グラフにループは作成されません。
コメント
- これについてはよくわかりません。
..
を親への一種の仮想ハードリンクと考える場合、リンクのターゲットが他の1つのリンクしか持てないという技術的な理由はありません。pwd
は、パスを解決するために別のアルゴリズムを使用する必要があります。
回答
この質問についてさらにいくつかのポイントを追加したいと思います。 Linuxではディレクトリへのハードリンクが許可されていますが、制限された方法です。
これをテストする1つの方法は、ディレクトリのコンテンツを一覧表示するときに、2つの特別なディレクトリ「。」を見つけることです。および「..」。みなさんご存じのとおり “。”同じディレクトリを指し、「..」は親ディレクトリを指します。
では、「a」がディレクトリ「b」を子とする親ディレクトリであるディレクトリツリーを作成しましょう。
a `-- b
ディレクトリ「a」のiノードを書き留めます。そして、ディレクトリ「a」からls -la
を実行すると、「。」が表示されます。ディレクトリも同じiノードを指しています。
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 a
ここで、ディレクトリ「a」に3つのハードリンクがあることがわかります。これは、iノード797358に「。」という名前の3つのハードリンクがあるためです。 「a」ディレクトリ内に「..」という名前を付け、ディレクトリ「b」内に「a」という名前を付けます。
$ 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 ..
ここで理解できますそのハードリンクは、親ディレクトリと子ディレクトリに接続するためのディレクトリにのみ存在します。したがって、子のないディレクトリには2つのハードリンクしかないため、ディレクトリ「b」には2つのハードリンクしかありません。
ディレクトリの自由なハードリンクが妨げられた理由の1つは、無限の参照ループを回避するためです。ファイルシステムをトラバースするプログラムを混乱させます。
ファイルシステムはツリーとして編成されており、ツリーは循環参照を持つことができないため、これは回避する必要があります。
コメント
- 良い例。それは私の疑いをクリアしました。したがって、これらのケースは、無限ループを回避するために特別な方法で処理されます。正しい?
- ディレクトリのハードリンクを許可する方法は限られているため、” .. “および”。”無限ループに到達しないため、無限ループが発生しないため、これらを回避するための特別な方法は必要ありません:)
回答
ディレクトリへのハードリンクを禁止する本当の理由は、次のどれでもありません。それぞれの問題はかなり簡単に解決できます。
- ツリー構造のサイクルは困難なトラバーサルを引き起こします
- 複数の親、つまり「本当の」親はどれですか?
- ファイルシステムのガベージコレクション
本当の理由(@ThorbjørnRavnが示唆) Andersen)は、iv id = “a7e4d30def”が指すディレクトリから、複数の親を持つディレクトリを削除すると表示されます。 >
:
..
は何を指す必要がありますか?
ディレクトリが親から削除されているが、リンク数が多い場合まだ0
より大きい場合は、どこかにまだそれを指している何かがあるはずです。 ..
を何も指さないままにすることはできません。多くのプログラムは..
に依存しているため、システムはをトラバースする必要があります。 ..
を更新するために、削除されたディレクトリを指す最初のものが見つかるまで、ファイルシステム全体。それか、ファイルシステムは次のリストを維持する必要があります。ハードリンクされたディレクトリを指すすべてのディレクトリ。
どちらの場合も、これはパフォーマンスオーバーヘッドになります。ファイルシステムのメタデータやコードの余分な複雑さのため、設計者はそれを許可しないことにしました。
コメント
- その’も簡単に解決できます。子ディレクトリの親のリストを保持し、子へのリンクを追加または削除するときに更新します。正規の親(子のターゲット’ s
)、リスト内の他の親の1つを指すように
..
を更新します。 - 同意します。解決すべきロケット科学ではありません。ただし、それでもパフォーマンスのオーバーヘッドが発生し、ファイルシステムのメタデータに少し余分なスペースが必要になり、複雑さが増します。そのため、設計者はシンプルで高速なアプローチを採用しました。’ハードディレクトリへのリンクを許可しないでください。
- dirsへのシンボリックリンク”解決されたセマンティクスと動作に違反します”、それでも許可されます。したがって、一部のコマンドには、シンボリックリンクをたどるかどうかを制御するオプションが必要です(例:findおよびcpの-L)。プログラムが’ .. ‘に従うと、さらに混乱が生じます。したがって、トラバース後のpwdと/ bin / pwdからの出力に違いがあります。シンボリックリンク。 ” Unixの回答はありません”;ただ設計上の決定。これは、私の答えで述べたように、” .. “がどうなるかを中心に展開しています。残念ながら、’ .. ‘は’他の誰もが答えに言及していません
- BTW、私は’ハードリンクを支持して’ mと言っているのではありません。 dirsに。どういたしまして。 ‘日常の仕事をこれまで以上に難しくしたくない。
- ‘ではないPOSIXによると、IMO ‘ .. ‘はファイルシステムの概念ではなく、パス上で構文的に解決されるため、
a/..
は常に.
を意味します。ところで、これがURLの仕組みです。 ‘が’を解決するブラウザです’ .. ‘サーバーに到達する前。そして、それはうまく機能します。
回答
ディレクトリでのハードリンクの作成は元に戻せません。次のようなものがあるとします:
/dir1 ├──this.txt ├──directory │ └──subfiles └──etc
/dir2
にハードリンクします。
つまり/dir2
には、これらすべてのファイルとディレクトリも含まれるようになりました
気が変わったらどうなりますか? rmdir /dir2
(空ではないため)
そして、/dir2
で再帰的に削除することはできません。 .. /dir1
からも削除されます!
IMHOこれを回避する十分な理由です!
編集:
コメントでは、ディレクトリに対してrm
を実行してディレクトリを削除することを提案しています。ただし、空でないディレクトリのrm
は失敗し、ディレクトリがハードリンクされているかどうかに関係なく、この動作を維持する必要があります。したがって、リンクを解除するためにrm
だけを使用することはできません。rm
に新しい引数が必要になります。参照カウントが1より大きい場合は、ディレクトリのリンクを解除するだけです。」
これは、驚くことではない別の原則を破ります。つまり、作成したばかりのディレクトリハードリンクの削除は削除と同じではありません。通常のファイルのハードリンクの…
文を言い換えます:さらに開発しないと、ハードリンクの作成を元に戻すことはできません(現在のコマンドは現在の動作と矛盾せずに削除を処理できないため)
ケースを処理するためにさらに開発を許可した場合、落とし穴の数、およびデータ損失のリスク 「このような開発が意味するように、システムがどのように機能するかを十分に認識していないことは、ディレクトリのハードリンクを制限する十分な理由です。
コメント
- それは問題ではないはずです。あなたの場合、dir2へのハードリンクを作成するとき、dir1のすべてのコンテンツへのハードリンクを作成する必要があるため、dir2の名前を変更または削除すると、iノードへの余分なリンクのみが削除されます。また、iノードへのリンク(dir1)が少なくとも1つあるため、dir1とそのコンテンツに影響を与えることはありません。
- 引数が正しくありません。リンクを解除するだけで、rm-rfは実行しません。また、リンク数が0に達すると、システムはすべてのコンテンツも削除できることを認識します。
- その’は多かれ少なかれすべての
rm
はとにかく下にあります(リンクを解除します)。参照: unix.stackexchange.com/questions/151951/ … これは実際には問題は、ハードリンクされたファイルの場合以上です。リンクを解除すると、名前付き参照が削除され、リンク数が減少します。rmdir
が’空でないディレクトリを削除しないという事実は関係ありません-‘dir1
の場合も同様です。ハードリンクは’データのコピーではなく、実際のファイルと同じであるため、実際には”削除” dir2ファイルは、dir1のディレクトリリストを消去します。リンクを解除する必要があります。 -
rm
であるため、通常のファイルのようにリンクを解除することはできません。’ディレクトリ don ‘ t で、’が空でない場合は、リンクを解除します。編集を参照してください。
回答
これは良い説明です。 「複数の親のうちのどれを指す必要がありますか?」について1つの解決策は、プロセスがiノードまたは文字列として完全なwdパスを維持することです。名前を変更できるため、iノードはより堅牢になります。少なくとも昔は、開いているファイルごとにコア内のiノードがあり、ファイルが開かれるたびにインクリメントされ、閉じられるとデクリメントされていました。それがゼロに達すると、それとそれが指していたストレージが解放されます。ファイルが誰にも開かれなくなると、そのファイル(コア内コピー)は破棄されます。これにより、サブディレクトリが別のプロセスのパスにあるときに、他のプロセスがディレクトリを別のディレクトリに移動した場合に、パスが有効なままになります。開いているファイルを削除する方法と似ていますが、ディレクトリから削除されるだけですが、開いているすべてのプロセスに対して開いたままです。
Bell Labs UNIXでは、ハードリンクディレクトリは以前は自由に許可されていました。少なくともV6とV7、バークレー以降についてはわかりません。フラグは必要ありません。ループを作成できますか?はい、そうしないでください。ループを作成すると、何をしているのかが非常に明確になります。もう一方の端が隔壁のフックから便利にぶら下がっている場合は、飛行機からスカイダイビングする順番を待っている間、首に結び目を作る練習をする必要はありません。
何今日は、lhomeをhomeにハードリンクして、/ homeが自宅のオートマウスで覆われているかどうかに関係なく、/ home / administを利用できるようにすることを望んでいました。そのオートマウントには、administという名前のシンボリックリンクがあります。 / lhome / administに。これにより、プライマリホームファイルシステムの状態に関係なく機能する管理アカウントを持つことができます。これはLinuxの実験ですが、UCBベースのSunOSでは、自動マウントがASCII文字列レベルで行われることを一度に学んだと思います。他の方法で、任意のFSの上のレイヤーとしてそれらをどのように実行できるかを理解するのは困難です。
他の場所でそれを読みました。と..もディレクトリ内のファイルではなくなりました。これらすべてには正当な理由があると確信しており、そのようなことで私たちが楽しんでいること(NTFSをマウントできることなど)の多くは可能ですが、UNIXの優雅さの一部は実装にありました。このエレガンスが提供する一般性や展性などの利点が、非常に堅牢で40年間耐えることを可能にしました。エレガントな実装を失うと、最終的にはWindowsのようになります(私が間違っているといいのですが!)。次に、誰かがエレガントな原則に基づいた新しいOSを作成します。考えるべきこと。おそらく私は間違っています、私は(明らかに)現在の実装に精通していません。 30年前の理解がLinuxにどれほど当てはまるかは、 驚くべきことです…ほとんどの場合!
コメント
- 私は間違っているかもしれませんが、
.
と..
は、最近のファイルシステムではファイルシステムのハードリンクではないと思います。ただし、ファイルシステムドライバはそれらを偽造します。ディレクトリのハードリンクを停止するのはこれらのファイルシステムです。古いファイルシステムの場合、それは可能でした(しかし危険です)。試していることを実行するには、mount --bind
を参照してください。また、mount --make…
およびおそらくコンテナも参照してください。
回答
私が収集した主な理由は、ディレクトリ名を使用する実行中のプログラムを台無しにすることなくディレクトリ名を変更できると便利だからです。他のファイルを参照するための作業ディレクトリ。Wineを使用して~/.newwineprefix/drive_c/Program Files/Firefox/Firefox.exe
を実行し、代わりにプレフィックス全体を~/.wine
に移動するとします。なんらかの奇妙な理由でFirefoxが../../windows
を参照してdrive_c/windows
にアクセスしていた場合、名前を~/.newwineprefix
に変更すると中断します親ディレクトリをinodeではなくテキスト文字列として追跡する..
の実装。
単一の親ディレクトリのinodeを保存することは、試すよりも簡単である必要があります。すべてのパスをテキスト文字列と一連のinodeの両方として追跡するため。
もう1つの理由は、その誤動作です。 ngアプリケーションはループを作成できる可能性があります。動作するアプリケーションは、ディレクトリをそれ自体に移動できないのと同じように、移動されるディレクトリのiノードが移動先のネストされたディレクトリのiノードと同じであるかどうかを確認できる必要があります。ファイルシステムレベルで強制されない場合があります。
さらに別の理由として、ディレクトリをハードリンクできる場合は、変更できないディレクトリのハードリンクを防止したい場合があります。 find
は、他のユーザーが作成したファイルを一時ディレクトリからクリアするために使用されるため、セキュリティ上の考慮事項があります。これは、ユーザーがシンボリックリンクの実ディレクトリを切り替えたときに問題が発生する可能性があります。find
は別のコマンドを呼び出しています。重要なディレクトリをハードリンクできると、管理者はそれらに影響を与えないようにfind
にテストを追加する必要があります(わかりました、すでに「ファイルに対してこれを行うことができないため、この理由は無効です。)
さらに別の理由は、親ディレクトリのinodeを保存すると、ファイルシステムの破損や損傷の場合に追加の冗長性が提供される可能性があることです。 ..
に、このディレクトリにハードリンクしているすべての親ディレクトリを一覧表示したかったので、現在のディレクトリがリンク解除された場合、別の任意の親を簡単に見つけることができます。リンクが等しい場合は、ファイルシステムがinodeを格納および使用する方法を変更する必要があります。プログラムにパスをシリーズとして処理させる(uniqディレクトリinodeの各ハードリンクにより、これは回避されますが、ファイルシステムが損傷した場合の冗長性は得られません。
..
はどこを指す必要がありますか?特にこれへのハードリンクを削除した後ディレクトリ、..
が指すディレクトリ内?どこかを指す必要があります。..
は’ドライブに物理的に存在する必要はありません。’はオペレーティングシステム’の仕事です。とにかく、現在の作業ディレクトリを追跡するので、各プロセスに関連付けられたLinuxのリストも保持するのは比較的簡単なはずです