Linux上のiノードについて知りたいと思ったことすべて

Linuxファイルシステムはiノードに依存しています。ファイルシステムの内部動作のこれらの重要な部分は、しばしば誤解されています。それらが何であるか、そしてそれらが何をするかを正確に見てみましょう。

ファイルシステムの要素

定義上、ファイルシステムはファイルを保存する必要があり、ファイルにはディレクトリも含まれています。ファイルはディレクトリ内に保存され、これらのディレクトリはサブディレクトリを持つことができます。どこかで、すべてのファイルがファイルシステム内のどこにあるか、ファイルの名前、所属するアカウント、所有するアクセス許可などを記録する必要があります。この情報は、他のデータを説明するデータであるため、メタデータと呼ばれます。

Linux ext4ファイルシステムでは、iノード構造とディレクトリ構造が連携して、すべてのファイルとディレクトリのすべてのメタデータを格納する基盤となるフレームワークを提供します。彼らはそれのようなカーネル、ユーザアプリケーション、またはLinuxユーティリティを、だかどうか、それを必要とする誰にでも利用可能なメタデータを作成しlsstat、とdf

iノードとファイルシステムのサイズ

確かに構造のペアがありますが、ファイルシステムにはそれ以上のものが必要です。各構造には何千ものものがあります。すべてのファイルとディレクトリにはiノードが必要です。すべてのファイルはディレクトリ内にあるため、すべてのファイルにはディレクトリ構造も必要です。ディレクトリ構造は、ディレクトリエントリまたは「ディレクトリ」とも呼ばれます。

各iノードには、ファイルシステム内で一意のiノード番号があります。同じiノード番号が複数のファイルシステムに表示される場合があります。ただし、Linuxシステムにマウントされているファイルシステムの数に関係なく、ファイルシステムIDとiノード番号が組み合わされて一意の識別子になります。

Linuxでは、ハードドライブやパーティションをマウントしないことを忘れないでください。パーティション上にあるファイルシステムをマウントするので、気付かないうちに複数のファイルシステムを持つのは簡単です。1つのドライブに複数のハードドライブまたはパーティションがある場合は、複数のファイルシステムがあります。それらは同じタイプ(たとえば、すべてext4)である可能性がありますが、それでも別個のファイルシステムになります。

すべてのiノードは1つのテーブルに保持されます。ファイルシステムは、iノード番号を使用して、そのiノードが配置されているiノードテーブルへのオフセットを簡単に計算します。iノードの「i」がインデックスを表す理由がわかります。

iノード番号を含む変数は、ソースコードで32ビットの符号なし長整数として宣言されています。つまり、iノード番号は最大サイズが2 ^ 32の整数値であり、4,294,967,295と計算されます。これは40億のiノードをはるかに超えています。

これが理論上の最大値です。実際には、ext4ファイルシステムのiノードの数は、ファイルシステムの容量16KBあたり1つのiノードのデフォルトの比率でファイルシステムが作成されるときに決定されます。ファイルとディレクトリはファイルシステム内に作成されるため、ファイルシステムの使用中にディレクトリ構造がオンザフライで作成されます。

コンピューターのファイルシステムにあるiノードの数を確認するために使用できるコマンドがあります。コマンドの-i(inodes)オプションは、df出力をiノードの数で表示するように指示します。

最初のハードドライブの最初のパーティションにあるファイルシステムを確認するので、次のように入力します。

df -i / dev / sda1

出力は次のようになります。

  • ファイルシステム:報告されているファイルシステム。
  • iノード:このファイルシステム内のiノードの総数。
  • IUsed:使用中のiノードの数。
  • IFree:使用可能な残りのiノードの数。
  • IUse%:使用されたiノードのパーセンテージ。
  • マウント先:このファイルシステムのマウントポイント。

このファイルシステムでは、iノードの10%を使用しました。ファイルはディスクブロックのハードドライブに保存されます。各iノードは、それらが表すファイルの内容を格納するディスクブロックを指します。数百万の小さなファイルがある場合、ハードドライブの容量が不足する前にiノードが不足する可能性があります。しかし、それは非常に難しい問題です。

以前は、電子メールメッセージを個別のファイルとして保存する一部のメールサーバー(これにより、小さなファイルの大規模なコレクションが急速に発生しました)でこの問題が発生していました。ただし、これらのアプリケーションがバックエンドをデータベースに変更すると、問題は解決しました。平均的なホームシステムではiノードが不足することはありません。これは、ext4ファイルシステムでは、ファイルシステムを再インストールせずにiノードを追加できないためです。

ファイルシステム上のディスクブロックのサイズを確認するにblockdevは、--getbsz(ブロックサイズの取得)オプションを指定してコマンドを使用できます。

sudo blockdev --getbsz / dev / sda

ブロックサイズは4096バイトです。

-B(ブロックサイズ)オプションを使用して、4096バイトのブロックサイズを指定し、通常のディスク使用量を確認しましょう。

df -B 4096 / dev / sda1

この出力は次のことを示しています。

  • ファイルシステム:レポート対象のファイルシステム。
  • 4Kブロック:このファイルシステム内の4KBブロックの総数。
  • 使用済み使用中の4Kブロックの数。
  • 使用可能使用可能な残りの4KBブロックの数。
  • 使用率使用された4KBブロックのパーセンテージ。
  • マウント先:このファイルシステムのマウントポイント。

この例では、ファイルストレージ(およびiノードとディレクトリ構造のストレージ)がこのファイルシステムのスペースの28%を使用し、iノードの10%を犠牲にしているため、良好な状態です。

iノードメタデータ

ファイルのiノード番号を確認するにlsは、-i(inode)オプションを使用できます。

ls -i geek.txt

このファイルのiノード番号は1441801であるため、このiノードはこのファイルのメタデータと、従来、ファイルがハードドライブ上にあるディスクブロックへのポインターを保持します。ファイルが断片化されているか、非常に大きいか、またはその両方である場合、iノードが指すブロックの一部は他のディスクブロックへのさらなるポインターを保持する可能性があります。また、これらの他のディスクブロックの一部は、別のディスクブロックのセットへのポインタを保持している場合もあります。これにより、iノードが固定サイズであり、ディスクブロックへの有限数のポインタを保持できるという問題が克服されます。

その方法は、「エクステント」を利用する新しいスキームに取って代わられました。これらは、ファイルの保存に使用される連続ブロックの各セットの開始ブロックと終了ブロックを記録します。ファイルが断片化されていない場合は、最初のブロックとファイルの長さを保存するだけで済みます。ファイルが断片化されている場合は、ファイルの各部分の最初と最後のブロックを保存する必要があります。この方法は(明らかに)より効率的です。

ファイルシステムがディスクブロックポインタまたはエクステントを使用しているかどうかを確認したい場合は、iノードの内部を調べることができます。これを行うにはdebugfs-R(request)オプションを指定してコマンドを使用し、対象のファイルのiノードを渡します。これはdebugfs 、内部の「stat」コマンドを使用してiノードの内容を表示するように要求 します。iノード番号はファイルシステム内でのみ一意であるため、iノードが存在するファイルシステムにも通知debugfs する必要があります。

このコマンド例は次のようになります。

sudo debugfs -R "stat" / dev / sda1

以下に示すように、debugfsコマンドはiノードから情報を抽出して次の場所に表示しますless

次の情報が表示されます。

  • iノード:私たちが見ているiノードの数。
  • タイプ:これは通常のファイルであり、ディレクトリやシンボリックリンクではありません。
  • モード:8進数のファイル権限。
  • フラグ:さまざまな機能を表すインジケーター。0x80000は「エクステント」フラグです(これについては以下で詳しく説明します)。
  • 生成:ネットワークファイルシステム(NFS)は、誰かがネットワーク接続を介してリモートファイルシステムにアクセスするときに、ローカルマシンにマウントされているかのようにこれを使用します。iノードと世代番号はファイルハンドルの形式として使用されます。
  • バージョン:iノードバージョン。
  • ユーザー:ファイルの所有者。
  • グループ:ファイルのグループ所有者。
  • プロジェクト:常にゼロである必要があります。
  • サイズ:ファイルのサイズ。
  • ファイルACL:ファイルアクセス制御リスト。これらは、所有者グループに属していない人々に制御されたアクセスを提供できるように設計されています。
  • リンク:ファイルへのハードリンクの数。
  • Blockcount:512バイトのチャンクで指定された、このファイルに割り当てられたハードドライブスペースの量。私たちのファイルには、これらのうち8つ、つまり4,096バイトが割り当てられています。したがって、98バイトのファイルは単一の4,096バイトのディスクブロック内にあります。
  • フラグメント:このファイルはフラグメント化されていません。(これは廃止されたフラグです。)
  • Ctime:ファイルが作成された時刻。
  • Atime:このファイルが最後にアクセスされた時刻。
  • Mtime:このファイルが最後に変更された時刻。
  • Crtime:ファイルが作成された時刻。
  • 追加のiノードフィールドのサイズ:ext4ファイルシステムでは、フォーマット時に、より大きなオンディスクiノードを割り当てる機能が導入されました。この値は、iノードが使用している追加のバイト数です。この余分なスペースは、新しいカーネルの将来の要件に対応したり、拡張属性を格納したりするためにも使用できます。
  • iノードチェックサム:このiノードのチェックサム。iノードが破損しているかどうかを検出できます。
  • エクステント:エクステントが使用されている場合(ext4では、デフォルトでエクステントが使用されます)、ファイルのディスクブロックの使用に関するメタデータには、フラグメント化されたファイルの各部分の開始ブロックと終了ブロックを示す2つの番号があります。これは、ファイルの各部分が占めるすべてのディスクブロックを保存するよりも効率的です。小さなファイルがこのブロックオフセットで1つのディスクブロックにあるため、エクステントが1つあります。

ファイル名はどこにありますか?

これでファイルに関する多くの情報が得られましたが、お気づきかもしれませんが、ファイル名を取得できませんでした。ここで、ディレクトリ構造が役立ちます。Linuxでは、ファイルと同じように、ディレクトリにはiノードがあります。ただし、ディレクトリiノードは、ファイルデータを含むディスクブロックを指すのではなく、ディレクトリ構造を含むディスクブロックを指します。

iノードと比較すると、ディレクトリ構造にはファイルに関する限られた量の情報が含まれています。ファイルのiノード番号、名前、および名前の長さのみを保持します。

iノードとディレクトリ構造には、ファイルまたはディレクトリについて知っておく必要のあるすべてのもの(またはアプリケーション)が含まれています。ディレクトリ構造はディレクトリディスクブロック内にあるため、ファイルが存在するディレクトリがわかります。ディレクトリ構造により、ファイル名とiノード番号がわかります。iノードは、タイムスタンプ、アクセス許可、ファイルシステム内のファイルデータの場所など、ファイルに関するその他すべての情報を提供します。

ディレクトリiノード

ディレクトリのiノード番号は、ファイルの場合と同じように簡単に確認できます。

次の例ではls 、-l(long format)、-i(inode)、および-d(directory)オプションを使用して、workディレクトリを確認します。

ls -lid work /

-d(ディレクトリ)オプションを使用したためls、ディレクトリの内容ではなく、ディレクトリ自体についてレポートします 。このディレクトリのiノードは1443016です。

homeディレクトリに対してこれを繰り返すには、次のように入力します。

ls -lid〜

homeディレクトリのiノードは1447510で、workディレクトリはホームディレクトリにあります。それでは、workディレクトリの内容を見てみましょう。-d(ディレクトリ)オプションの代わりに、  (-aすべて)オプションを使用します。これにより、通常は非表示になっているディレクトリエントリが表示されます。

次のように入力します。

ls -lia work /

-a(すべて)オプションを使用したため、シングルドット(。)およびダブルドット(..)のエントリが表示されます。これらのエントリは、ディレクトリ自体(シングルドット)とその親ディレクトリ(ダブルドット)を表します。

シングルドットエントリのiノード番号を見ると、1443016であることがわかりますwork。これは、ディレクトリのiノード番号を検出したときに取得したものと同じです。また、ダブルドットエントリのiノード番号は、homeディレクトリのiノード番号と同じです。

そのため、このcd ..コマンドを使用して、ディレクトリツリーのレベルを上に移動できます。同様に、アプリケーション名またはスクリプト名の前に。を付けると./、アプリケーションまたはスクリプト  をどこから起動するかをシェルに通知します。

iノードとリンク

これまで説明してきたように、ファイルシステムに整形式でアクセス可能なファイルを含めるには、ファイル、ディレクトリ構造、およびiノードの3つのコンポーネントが必要です。ファイルはハードドライブに保存されているデータであり、ディレクトリ構造にはファイルの名前とそのiノード番号が含まれ、iノードにはファイルのすべてのメタデータが含まれています。

シンボリックリンクはファイルのように見えるファイルシステムエントリですが、実際には既存のファイルまたはディレクトリを指すショートカットです。彼らがこれをどのように管理し、これを達成するために3つの要素がどのように使用されるかを見てみましょう。

以下に示すように、2つのファイルを含むディレクトリがあるとします。1つはスクリプトで、もう1つはアプリケーションです。

lnコマンドと-s(シンボリック)オプションを使用して、次のようにスクリプトファイルへのソフトリンクを作成できます。

ls -s my_script geek.sh

my_script.shと呼ばれるへのリンクを作成しましたgeek.sh。次のls ように入力して、2つのスクリプトファイルを確認するために使用 できます。

ls -li * .sh

のエントリgeek.sh は青色で表示されます。権限フラグの最初の文字はリンクの「l」であり、を ->指しmy_script.shます。これはすべて、それgeek.shがリンクであることを示しています。

ご想像のとおり、2つのスクリプトファイルのiノード番号は異なります。ただし、もっと驚くべきことは、ソフトリンクgeek.shが元のスクリプトファイルと同じユーザー権限を持っていないことです。実際、のアクセス許可 geek.shははるかに自由です。すべてのユーザーが完全なアクセス許可を持っています。

のディレクトリ構造にgeek.shは、リンクの名前とそのiノードが含まれています。リンクを使おうとすると、通常のファイルと同じように、そのiノードが参照されます。リンクiノードはディスクブロックを指しますが、ファイルコンテンツデータを含む代わりに、ディスクブロックには元のファイルの名前が含まれます。ファイルシステムは元のファイルにリダイレクトします。

元のファイルを削除し、次のように入力して内容を表示するとどうなるかを確認します geek.sh

rm my_script.sh
猫オタク.sh

シンボリックリンクが壊れており、リダイレクトは失敗します。

次に、次のように入力して、アプリケーションファイルへのハードリンクを作成します。

lnスペシャルアプリオタクアプリ

これら2つのファイルのiノードを確認するには、次のように入力します。

ls -li

どちらも通常のファイルのように見えます。geek-appそれがlsリストのようにリンクであることを示すものは何もありませんgeek.sh。さらに、 geek-app 元のファイルと同じユーザー権限があります。ただし、驚くべきことは、両方のアプリケーションのiノード番号が同じ1441797であることです。

のディレクトリエントリにgeek-appは、「geek-app」という名前とiノード番号が含まれていますが、元のファイルのiノード番号と同じです。したがって、同じiノードを指す異なる名前の2つのファイルシステムエントリがあります。実際、任意の数のアイテムが同じiノードを指すことができます。

次のように入力し、statプログラムを使用してターゲットファイルを確認します。

statspecial-app

2つのハードリンクがこのファイルを指していることがわかります。これはiノードに格納されます。

次の例では、元のファイルを削除し、秘密の安全なパスワードでリンクを使用しようとします。

rmスペシャルアプリ
./geek-appcorrecthorsebatterystaple

驚いたことに、アプリケーションは期待どおりに実行されますが、どのように実行されますか?これは、ファイルを削除すると、iノードが自由に再利用できるために機能します。ディレクトリ構造は、iノード番号がゼロであるとマークされ、ディスクブロックは、そのスペースに格納される別のファイルに使用できます。

ただし、iノードへのハードリンクの数が1より大きい場合、ハードリンクの数は1つ減り、削除されたファイルのディレクトリ構造のiノード数はゼロに設定されます。ハードドライブとiノード上のファイルの内容は、既存のハードリンクで引き続き利用できます。

次のように入力して、もう一度statを使用します—今回はgeek-app

統計オタク-アプリ

これらの詳細は、前のstatコマンドと同じiノード(1441797)から取得されます。リンク数が1つ減りました。

このiノードへのハードリンクが1つになっているため、を削除 geek-appすると、ファイルが本当に削除されます。ファイルシステムはiノードを解放し、ディレクトリ構造をゼロのiノードでマークします。新しいファイルは、ハードドライブ上のデータストレージを上書きできます。

関連:Linuxでstatコマンドを使用する方法

iノードのオーバーヘッド

それはきちんとしたシステムですが、オーバーヘッドがあります。ファイルを読み取るには、ファイルシステムは次のすべてを実行する必要があります。

  • 適切なディレクトリ構造を見つける
  • iノード番号を読み取る
  • 適切なiノードを見つける
  • iノード情報を読む
  • iノードリンクまたは関連するディスクブロックへのエクステントのいずれかをたどります
  • ファイルデータを読み取る

データが連続していない場合は、もう少しジャンプする必要があります。

ls 多くのファイルの長い形式のファイルリストを実行するために実行する必要がある作業を想像してみてください 。ls出力を生成するために必要な情報を取得するためだけに、前後に多くのことがあります。

もちろん、ファイルシステムへのアクセスを高速化することが、Linuxが可能な限り多くのプリエンプティブファイルキャッシングを実行しようとする理由です。これは非常に役立ちますが、他のファイルシステムと同様に、オーバーヘッドが明らかになる場合があります。

これで、その理由がわかります。