ディレクトリサイズが他のファイルと異なって報告されるのはなぜですか?

ディレクトリサイズが他のファイルと異なって報告されるのはなぜですか?

空のディレクトリがなぜ4096バイトのスペースを占めるのか知りたいです。これ質問。スペースがブロック単位で割り当てられるため、新しいディレクトリのサイズは4096バイトです。

しかし、「一般」ファイルの割り当てもブロック単位で実行されると確信しています。少なくともそうです。Windowsファイルシステム少なくともext*では似ているべきだと思います。

今、私が理解しているように、他の種類のファイル(ファイル、シンボリックリンクなど)のサイズのリストは実際のサイズに基づいて行われます。空のファイルを作成すると、サイズがゼロで表示されるためです。数文字を入力すると、<文字数>バイトがサイズなどで表示されます。

だから私の質問は他のファイルの割り当てもブロック単位で行われますが、レポートディレクトリとファイルサイズのポリシーはなぜ違うのですか?

言う

私はその質問が十分に明確だと思ったが、明らかにそうではなかった。私はここで問題を明確にしようとします。

1) 私が思うディレクトリは何ですか?

次の例では、ディレクトリの理解について説明します。読んでから間違った部分があれば教えてください。

というディレクトリがあるとしましょうmydirf0f1および3つのファイルが含まれているとしますf2。各ファイルの長さが1バイトであるとします。

さて、何ですかmydir?これは、文字列 "f0"とf0指定されたinode番号などの内容を含むinodeへのポインタです。文字列 "f1" とf1それが指す inode 番号。文字列「f2」とf2inode番号が指します。 (少なくとも私が思うディレクトリはそうです。私が間違っていたら訂正してください。)

これで、ディレクトリサイズを計算する方法は2つあります。

mydir1)指摘されたinodeのサイズを計算します。

2)コンテンツが指すインデックスノードのサイズを合計しますmydir

1がより直観的にずれても、これがどのように使用されるかを仮定します。 (この問題では実際にどのような方法を使用するかは重要ではありません。) すると、 のサイズは次のようにmydir計算されます。

2 + 2 + 2 + 3 * <space_required_to_store_an_inode_number>

2は、各ファイル名の長さが2バイトであるためです。

2) 質問:

問題は、ディレクトリが正しいと思うと仮定すると、mydir方法1を使用するか方法2を使用してサイズを計算するかにかかわらず、報告されたサイズは4096よりはるかに小さくなければならないことです。

4096バイトが報告される理由は、割り当てがブロック単位で行われるためであると言えます。したがって、報告されたサイズが大きすぎます。

しかし、次に述べると、一般ファイルの場合、割り当てもブロック単位で行われます。 (望むよりトリガーの答え注)それにもかかわらず、その寸法は実際の寸法として報告されます。 (1文字が含まれている場合は1バイト、2文字が含まれている場合は2バイトなど)

だから私の質問は、ポリシーレポートディレクトリのサイズがポリシーレポートの一般的なファイルサイズとなぜそんなに異なるのかということです。

追加の指示:

空でないファイルと空のディレクトリに割り当てられた初期ブロック数は8ブロックであることがわかります。 (望むよりトリガーの答え)では、通常のファイルとディレクトリに同じ数のブロックが割り当てられていますが、報告されたディレクトリサイズがはるかに大きいのはなぜですか?

答え1

私の考えでは、あなたが混乱している理由は、ディレクトリが何であるかわからないからだと思います。はい。そのために一歩踏み出して、Unixファイルシステムがどのように機能するかを見てみましょう。

Unixファイルシステムはいくつですか?分離ディスクのデータアドレッシングの概念:

  • データブロックディスク上のブロックのセットです。コンテンツファイルの。
  • インデックスノード次のファイルのメタデータを含むファイルシステム内の一意の数値アドレスを持つファイルシステムの特殊ブロック。
    • 特権
    • アクセス/修正時間
    • サイズ
    • データブロックへのポインタ(ブロック、範囲などのリストにすることができます)
  • ファイル名inodeにマップされたファイルシステムのルートの階層的な位置。

つまり、「ファイル」は実際には次の3つから構成されます。

  1. ファイルシステムのPATH
  2. メタデータを持つインデックスノード
  3. inodeが指すデータブロック

ほとんどの場合、ユーザーはファイルを「ファイル名に関連付けられたエンティティ」の同義語として考えます。これは、低レベルのエンティティまたはファイル/ソケットAPIを扱うときにのみinodeまたはデータブロックを考える場合です。ディレクトリは、これらの下位レベルのエンティティの1つです。

ディレクトリは、複数の異なるファイルを含むファイルと考えることができます。これは半分だけ本当です。ディレクトリは、ファイル名を inode 番号にマップするファイルです。ファイルを「インクルード」しませんが、ファイル名へのポインタです。次の項目を含むテキストファイルだと思います。

  • 。 - インデックスノード1234
  • .. - アイノード200
  • ドキュメント - Inode 2008
  • README.txt - アイノード2009

上記の項目の名前は次のとおりです。ディレクトリエントリ。デフォルトでは、ファイル名から inode 番号へのマッピングです。ディレクトリは、ディレクトリエントリを含む特別なファイルです。

もちろん、これは単純化されていますが、基本的なアイデアと他のディレクトリの珍しい点について説明します。

  • ディレクトリが独自のサイズを知らないのはなぜですか?
    • これには他のコンテンツへのポインタのみが含まれているため、そのコンテンツを繰り返してサイズを見つける必要があります。
  • ディレクトリが空ではないのはなぜですか?
    • 少なくとも。と..エントリが含まれているためです。したがって、正しいディレクトリは、少なくともこれらのエントリを含めることができる最小のファイルサイズと同じくらい小さくなければなりません。ほとんどのファイルシステムでは少なくとも4096バイトです。
  • ファイル名を変更するときに親ディレクトリへの書き込み権限が必要なのはなぜですか?
    • これは、ファイルを変更するだけでなく、ファイルを指すディレクトリエントリも変更するためです。
  • lsがディレクトリに奇妙な数の「リンク」を表示するのはなぜですか?
    • ディレクトリは、それ自体、親ディレクトリ、およびサブディレクトリによって参照(リンク)できます。
  • ハードリンクの機能は何であり、シンボリックリンクとどう違うのですか?
    • ハードリンクが追加されましたディレクトリエントリ同じ inode 番号を指します。 inode番号を指すので、同じファイルシステム上のファイルのみを指すことができます(inodeはファイルシステムに対してローカルです)。
    • シンボリックリンクは、別々のファイル名を指す新しいinodeを追加します。ファイル名を参照するので、ツリー内のすべてのファイルを指すことができます。

しかし、待って!奇妙なことが起こっています!

ls -ld somedirectoryls -l somefileファイルサイズは、ファイルの実際のサイズではなく、常に4096として表示されます。なぜ?

混乱した点1:「サイズ」と言うと、次の2つを意味できます。

  • inodeに保存されたファイルサイズ
  • 割り当てサイズは、inodeに関連付けられたブロック数に各ブロックサイズを掛けた値です。

一般的に言えば、同じ数字ではありません。ジャンプしstatてみてください定期的なファイルを見ると、この違いを見ることができます。

ファイルシステムが空でないファイルを作成するときは、通常、データブロックをグループに割り当てます。これは、ファイルが高速で増減する傾向があるためです。ファイルシステムがファイルを表現するのに必要な数のデータブロックだけを割り当てると、増減が遅くなり、断片化が深刻な問題になります。したがって、実際には、ファイルシステムは小さな変更のためにスペースを再割り当てする必要はありません。これは、ディスクにファイルが「占有」されているが完全に使用されていない領域がたくさんある可能性があることを意味します。

ファイルシステムは、これらすべての未使用領域をどのように処理しますか?何もありません。必要性を感じるまで。ファイルシステムオプティマイザ(バックグラウンドで実行されているオンラインオプティマイザ、fsckの一部でも、ファイルシステム自体に組み込まれている場合もあります)がこのように感じられる場合は、ファイルのデータブロックを再割り当てできます。移動時にブロックが使用され、未使用のブロックが解放されます。ブロックなど

それでは、通常のファイルとディレクトリの違いを見てみましょう。ディレクトリはファイルシステムの「バックボーン」を形成するため、頻繁にアクセスまたは変更する必要があるため、最適化する必要があると予想できます。だからあなたは彼らが全く崩壊したくありません。ディレクトリが作成されると、常に最大出力ディレクトリエントリが多すぎても、すべてのデータブロックのサイズは同じです。ファイルとは異なり、ディレクトリは通常サイズと増加率が制限されているため、ディレクトリの場合は問題ありません。

4096報告されたディレクトリサイズは、ディレクトリ内のエントリの数ではなく、ディレクトリinodeに格納されている「ファイルサイズ」の数です。これは固定数字ではありません。ディレクトリに割り当てられたブロック数に合う最大バイト数。通常、これはすべてのコンテンツを含むファイルに割り当てられた512バイト/ブロック×8ブロックです。ただし、ディレクトリの場合、ファイルサイズと割り当てサイズは同じです。単一のグループに割り当てられるため、ファイルシステムオプティマイザはそのブロックを移動しません。

ディレクトリが大きくなるにつれて、より多くのデータブロックが割り当てられ、最大出力それに応じてファイルのサイズを変更してこれらのブロックをブロックします。

したがって、割り当てられたデータブロックのサイズに設定されたディレクトリinodeのファイルサイズフィールドが表示されますlsstat

答え2

初期空のディレクトリサイズはファイルシステムによって異なると思います。また、アクセス権を持つext3およびext4ファイルシステムから4096バイトの空のディレクトリを取得します。一種のNFSマウントNASでは、80バイトの空のディレクトリが表示されます。 ReiserFSファイルシステムへのアクセス権がなく、新しく作成された空のディレクトリのサイズが面白いでしょう。

従来、ディレクトリは、対応する inode (ファイルを記述するディスク構造) にディレクトリであることを示すビットが設定されたファイルです。ファイルは可変長レコードで埋められます。内容は次のとおりです/usr/include/linux/dirent.h

struct dirent64 {
    __u64       d_ino;
    __s64       d_off;
    unsigned short  d_reclen;
    unsigned char   d_type;
    char        d_name[256];
};

この値を使用してカタログファイルエントリをスキップできますd_off。エントリが削除されると(コマンドで使用されるunlink()システムコール)、欠落したレコードを説明するために前のエントリの値が増えます。どのレコードも「圧縮」されません。最も簡単な方法は、ディレクトリファイル内のすべてのエントリが何バイトを占有しているかを調べるか、単に把握するのではなく、ファイルに割り当てられたディスクブロックのバイト数に基づいて割り当てを表示することです。ディレクトリファイルには何バイトありますか?最後のアイテム。rmd_off

今日のディレクトリにはBツリーまたはハッシュツリー。ブロック単位でディレクトリを作成するとパフォーマンスが大幅に向上したり、既存のディレクトリと同様に内部に「空きスペース」があるため、ディレクトリの「実際のサイズ」(バイト)を決定するのが難しいと思います。 。しばらく使用されており、多くのファイルが削除され追加されました。ブロック数にブロックあたりのバイト数を掛けて表示する方が簡単です。

答え3

ファイルには割り当てられたブロックがない可能性があります。フラグは-sこれらのls違いを示しますが、ディレクトリには特定の数の最小ブロックが割り当てられ、デフォルトのサイズになります。 (これらの概念をウィンドウから投げるための素晴らしい最新のファイルシステムを使用しない限り)、たとえば、次のようになります。

% mkdir testfoo
% cd testfoo/
% mkdir foodir
% touch foofile
% ln -s foofile foosln
% ls -ld foo*
drwxrwxr-x  2 jmates  jmates  512 Oct  5 19:48 foodir
-rw-rw-r--  1 jmates  jmates    0 Oct  5 19:48 foofile
lrwxrwxr-x  1 jmates  jmates    7 Oct  5 19:48 foosln -> foofile
% ls -lds foo*
8 drwxrwxr-x  2 jmates  jmates  512 Oct  5 19:48 foodir
0 -rw-rw-r--  1 jmates  jmates    0 Oct  5 19:48 foofile
0 lrwxrwxr-x  1 jmates  jmates    7 Oct  5 19:48 foosln -> foofile
% 

必要な詳細を保存するために7バイトが割り当てられていますが、ここのシンボリックリンクはどのブロックも占有しません。readlink(2)本当に好奇心が多いです!とにかく、foofile1〜2バイトを入力してみましょう。

% echo >> foofile a
% ls -lds foo*
8 drwxrwxr-x  2 jmates  jmates  512 Oct  5 19:48 foodir
8 -rw-rw-r--  1 jmates  jmates    2 Oct  5 19:49 foofile
0 lrwxrwxr-x  1 jmates  jmates    7 Oct  5 19:48 foosln -> foofile
%

割り当てられたブロックが2バイト(追加および改行文字)だけfoofileジャンプされていることがわかります。8aecho

ファイルが稀です。これは、ファイルと対話するツールがスパースを処理する方法によって、報告されたファイルサイズが実際のコンテンツと異なる可能性があるというもう1つの理由です。

また、ディレクトリサイズを増やし、非常に長い名前を持つ多くのファイルを作成し、それぞれの新しい長いファイル名が生成された後、ディレクトリ(および割り当てられたブロック)のサイズに何が起こるかを確認できます。ls -lds .

関連情報