UnixベースのOSで空のディレクトリのリンク数が1ではなく2である理由については、多くの説明を見てきました。それらはすべて「。」が原因であると言っています。すべてのディレクトリが自分自身を指し示しているディレクトリ。 「。」の概念がある理由がわかります。相対パスを指定するのに便利ですが、ファイルシステムレベルで実装すると何が得られますか?シェルや、パスを取得するシステムコールだけがその解釈方法を知っているのではないでしょうか。
その「..」は実際のリンクであり、私にとってははるかに理にかなっています。ファイルシステムは、親ディレクトリに移動するために、親ディレクトリへのポインタを格納する必要があります。しかし、「。」の理由はわかりません。実際のリンクであることが必要です。また、実装で醜い特殊なケースにつながるようです-リンク数が1未満のiノードによって使用されているスペースしか解放できないと思うかもしれませんが、それらがディレクトリである場合は、実際に確認する必要がありますリンク数は2未満です。なぜ不整合があるのですか?
確かに興味深い質問です。一見すると、次のような利点があります。
まず、「.
"は、現在のディレクトリがシェルまたはシステムコールによって実行される可能性があるためです。ただし、ディレクトリにドットエントリがあると、実際にはこの必要性がなくなり、より低いレベルでの一貫性が強制されます。
しかし、これがこの設計決定の背後にある基本的な考えだったとは思いません。
ファイルがディレクトリから作成または削除されている場合、ディレクトリの変更タイムスタンプも更新する必要があります。このタイムスタンプはそのiノードに保存されます。 iノード番号は、対応するディレクトリエントリに格納されます。
[〜#〜] if [〜#〜]ドットエントリが存在しない場合、ルーチンは親ディレクトリのこのディレクトリのエントリでiノード番号を検索する必要があり、これにより再度ディレクトリ検索。
[〜#〜] but [〜#〜]幸い、現在のディレクトリにドットエントリがあります。現在のディレクトリでファイルを追加または削除するルーチンは、最初のエントリ(ドットエントリが通常存在する場所)にジャンプして、現在のディレクトリのiノード番号をすぐに見つけるだけです。
ドットエントリには3つ目の良い点があります。
fsck
が腐ったファイルシステムをチェックし、フリーリストにもない非接続ブロックを処理する必要がある場合、データブロック(ディレクトリリストとして解釈される場合)にドットがあるかどうかを簡単に確認できますiノードを指しているエントリは、このデータブロックを指すようになっています。その場合、このデータブロックは、再接続する必要がある失われたディレクトリと見なされる場合があります。
(うーん、次はちょっとした叙事詩です...)
UNIXのファイルシステム上のディレクトリの設計(これは、一般的には通常ですが、必ずしもUNIX OSに接続されているわけではありません)は素晴らしい洞察を表し、実際に必要な特殊なケースの数を減らします。
「ディレクトリ」は、実際にはファイルシステム内の単なるファイルです。ファイルシステム内のファイルの実際の内容はすべてinodesにあります(質問から、あなたはすでにこのことに気づいていることがわかります)。ディスク上のiノードに構造はありません。それらは、ディスク上にピーナッツバターのように広がった、番号の付いたバイトの塊の大きな束です。これは役に立たず、きちんと整頓された人には忌避されます。
only特殊iノードはiノード番号2です(伝統的な理由により、0または1ではありません)。 iノード2はディレクトリファイルですルートディレクトリ。システムがファイルシステムをマウントするとき、システムはそれ自体を開始するためにreaddir inode 2を実行する必要があることを「認識」しています。
ディレクトリファイルは単なるファイルであり、opendir(3)やその仲間が読むことを意図した内部構造を持っています。 (OSに応じて)dir(5)に記載されている内部構造を確認できます。これを見ると、ディレクトリファイルエントリにファイルに関する情報がほとんど含まれていないことがわかります。これはすべてファイルiノード内にあります。このファイルの特別な点の1つは、書き込みを許可するモードでディレクトリファイルを開こうとすると、open(2)関数でエラーが発生することです。他のさまざまなコマンド(例としてhexdump
を1つだけ取り上げます)は、ディレクトリファイルに対して通常の方法で動作することを拒否します。これは、おそらくそれがあなたがやりたいことではないからです(ただし、それはファイルシステムの特別なケースではありません)。 。
ハードリンクは、ディレクトリファイルのマップ内のエントリにすぎません。このようなマップには、同じiノード番号にマップする2つ(またはそれ以上)のエントリを含めることができます。そのため、そのiノードには2つ(またはそれ以上)のハードリンクがあります。 everyファイルに少なくとも1つの「ハードリンク」がある理由もこれで説明されています。 iノードには参照カウントがあり、ファイルシステムのどこかにあるディレクトリファイルでそのiノードが言及された回数が記録されます(これはls -l
を実行したときに表示される番号です)。
OK:私たちは今、要点に達しています。
ディレクトリファイルは、文字列(「ファイル名」)から数値(iノード番号)へのマップです。これらのiノード番号は、そのディレクトリにあるファイルのiノードの番号です。そのディレクトリにあるファイルには他のディレクトリファイルが含まれている可能性があるため、そのiノード番号はディレクトリにリストされているものの1つになります。したがって、ファイル/tmp/foo/bar
がある場合、ディレクトリファイルfoo
にはbar
のエントリが含まれ、その文字列をそのファイルのiノードにマッピングします。ディレクトリ/tmp
の「中」にあるディレクトリファイルfoo
のエントリも、ディレクトリファイル/tmp
にあります。
Mkdir(2)でディレクトリを作成すると、その関数は
最終結果は、(ほとんど)唯一の特別な場合です:
st_mode
を参照してください。(stackoverflowの元の質問、2011-10-20からコピー)