Linux の EXT シリーズファイルシステムフォーマットの詳細な説明

Linux の EXT シリーズファイルシステムフォーマットの詳細な説明

Linux ファイルシステム

一般的なハードディスクは上図のとおりです。各ディスクは複数のトラックに分割され、各トラックは複数のセクターに分割され、各セクターは 512 バイトで、ハードディスクの最小のストレージ単位です。ただし、オペレーティングシステムレベルでは、複数のセクターがブロックに結合され、これがオペレーティングシステムのデータストレージの最小単位です。通常、8 つのセクターが 4K バイトのブロックを形成します。
Linux ファイル システムの場合、考慮すべき点がいくつかあります。

  • ファイルをブロック単位で保存できるように、ファイル システムは厳密な編成形式を持つ必要があります。
  • ファイル システムには、ファイルの複数のブロックが配置されている場所を見つけやすくするためのインデックス領域が必要です。
  • 最近頻繁に読み書きされるファイルがある場合は、キャッシュ層が必要です
  • ファイルは管理と検索を容易にするためにフォルダに整理する必要があります
  • Linux カーネルは、どのファイルがどのプロセスによって開かれ、使用されているかを追跡するために、独自のメモリ内に一連のデータ構造を保持します。

Linux 内のすべてはファイルであり、次の種類のファイルがあります (ls -l 結果の最初の識別子からわかるように)。

  • - 通常のファイルを示します
  • dはフォルダを示す
  • cはキャラクタデバイスファイルを表す
  • bはブロックデバイスファイルを示します
  • sはソケットファイルを示します
  • lはソフトリンクを示す

iノードとブロックストレージ

EXT シリーズ形式を例に、ハードディスク上でファイルがどのように存在するかを見てみましょう。まず、ファイルはブロックに分割され、ハードディスク上に分散されます。これらのブロックを見つけてファイルのメタデータを記録するには、インデックス構造が必要です。これが inode です。i はインデックスを表します。 inode データ構造は次のとおりです。

構造体ext4_inode{
 __le16 i_mode; /* ファイルモード */
 __le16 i_uid; /* 所有者UIDの下位16ビット */
 __le32 i_size_lo; /* バイト単位のサイズ */
 __le32 i_atime; /* アクセス時間 */
 __le32 i_ctime; /* iノードの変更時刻 */
 __le32 i_mtime; /* 変更時刻 */
 __le32 i_dtime; /* 削除時刻 */
 __le16 i_gid; /* グループ ID の下位 16 ビット */
 __le16 i_links_count; /* リンク数 */
 __le32 i_blocks_lo; /* ブロック数 */
 __le32 i_flags; /* ファイルフラグ */
 ユニオン {
  構造体{
   __le32 l_i_バージョン;
  }linux1;
  構造体{
   __u32 h_i_トランスレータ;
  } ハード1;
  構造体{
   __u32 m_i_reserved1;
  } マシックス1;
 } osd1; /* OS依存1 */
 __le32 i_block[EXT4_N_BLOCKS];/* ブロックへのポインタ */
 __le32 i_generation; /* ファイルバージョン(NFS用) */
 __le32 i_file_acl_lo; /* ファイル ACL */
 __le32 i_size_high;
 __le32 i_obso_faddr; /* 廃止されたフラグメントアドレス */
 ユニオン {
  構造体{
   __le16 l_i_blocks_high; /* l_i_reserved1 でした */
   __le16 l_i_file_acl_high;
   __le16 l_i_uid_high; /* これら 2 つのフィールド */
   __le16 l_i_gid_high; /* 予約済み2[0] */
   __le16 l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */
   __le16 l_i_予約済み;
  }linux2;
  構造体{
   __le16 h_i_reserved1; /* ext4 で削除された廃止されたフラグメント番号/サイズ */
   __u16 h_i_mode_high;
   __u16 h_i_uid_high;
   __u16 h_i_gid_high;
   著者:
  } ハード2;
  構造体{
   __le16 h_i_reserved1; /* ext4 で削除された廃止されたフラグメント番号/サイズ */
   __le16 m_i_file_acl_high;
   __u32 m_i_reserved2[2];
  } マシックス2;
 } osd2; /* OS依存2 */
 __le16 i_extra_isize;
 __le16 i_checksum_hi; /* crc32c(uuid+inum+inode) BE */
 __le32 i_ctime_extra; /* 追加変更時間 (nsec << 2 | エポック) */
 __le32 i_mtime_extra; /* 追加の変更時間(nsec << 2 | エポック) */
 __le32 i_atime_extra; /* 追加アクセス時間 (nsec << 2 | エポック) */
 __le32 i_crtime; /* ファイル作成時刻 */
 __le32 i_crtime_extra; /* 追加のファイル作成時間 (nsec << 2 | エポック) */
 __le32 i_version_hi; /* 64 ビット版の上位 32 ビット */
 __le32 i_projid; /* プロジェクトID */
};

このうち、__le32 i_block[EXT4_N_BLOCKS]はデータブロックへの参照を格納します。EXT4_N_BLOCKSは次のように定義されます。

#EXT4_NDIR_BLOCKS 12 を定義する
#定義 EXT4_IND_BLOCK EXT4_NDIR_BLOCKS
#定義 EXT4_DIND_BLOCK (EXT4_IND_BLOCK + 1)
#EXT4_TIND_BLOCK (EXT4_DIND_BLOCK + 1) を定義します
#EXT4_N_BLOCKS (EXT4_TIND_BLOCK + 1) を定義します

ext2 および ext3 では、i_block の最初の 12 項目にはデータ ブロックへの直接参照が格納され、13 番目の項目には間接ブロックへの参照が格納され、データ ブロックの位置は間接ブロックに格納されます。同様に、14 番目の項目には 2 次間接ブロックの位置が格納され、15 番目の項目には 3 次間接ブロックの位置が格納されます (次の図を参照)。

大きなファイルの場合、対応するブロックを見つけるためにハードディスクを複数回読み取る必要があることは容易に理解できます。この問題を解決するために、ext4 ではエクステント ツリーが提案されています。基本的な考え方は、各ブロックの位置を 1 つずつ記録するのではなく、連続するブロックを開始位置とブロック数で表すことで、ストレージ スペースを節約することです。まず、i_block 内の元の 415 = 60 バイトのスペースを、エクステント ヘッダー (ext4_extent_header) と 4 つのエクステント エントリ (ext4_extent) に置き換えます。これは、ext4_extent_header と ext4_extent の両方が 12 バイトを占めるためです。 ee_len の最初のビットは初期化されているかどうかを判断するために使用されるため、最大 32K の数値を保存することもできます。したがって、エクステント エントリには最大 32K4K=128M のデータが保存できます。ファイルが 4128M=512M より大きい場合、またはファイルが 4 つ以上の連続していないブロックに保存されている場合は、inode の i_block 構造を拡張する必要があります。そのエクステントエントリは、ext4_extent から 4K バイトのブロックを指す ext4_extent_idx 構造に変更する必要があります。ヘッダーが占める 12 バイトを除いて、340 個の ext4_extent を保存でき、保存できるデータの最大量は 340128M=42.5G です。このインデックス構造は、ファイルが連続したブロックに保存される場合に非常に効率的であることがわかります。

構造体 ext4_extent_header {
 __le16 eh_magic; /* ext4 エクステント識別子: 0xF30A */
 __le16 eh_entries; /* 現在のレベル内の有効なノードの数*/
 __le16 eh_max; /* 現在のレベルのノードの最大数*/
 __le16 eh_depth; /* ツリーの現在のレベルの深さ。0 はリーフ ノード、つまりデータ ノード、>0 はインデックス ノードを表します*/
 __le32 eh_世代; 
}
構造体ext4_extent{
 __le32 ee_block; /* エクステントの開始ブロック論理番号*/
 __le16 ee_len; /* エクステントに含まれるブロックの数*/
 __le16 ee_start_hi; /*エクステント開始ブロックの物理アドレスの上位16ビット*/
 __le32 ee_start_lo; /*エクステント開始ブロックの物理アドレスの下位32ビット*/
}; //データノードのextent_body形式 struct ext4_extent_idx {
 __le32 ei_block; /* インデックスがカバーするファイル範囲の開始ブロックの論理シーケンス番号*/
 __le32 ei_leaf_lo; /* 次のレベルエクステントのブロックの物理アドレスの下位 32 ビットを格納します */ 
 __le16 ei_leaf_hi; /* 次のレベルのエクステントを格納するブロックの物理アドレスの上位 16 ビット */
 __u16 ei_未使用;

}; //インデックスノードのextent_body形式

/var/log/messages ファイルの例を以下に示します。

Inode ビットマップとブロック ビットマップ

ハード ディスクには、ブロック データと inode を保存するための専用領域があります。ただし、新しいファイルを作成する場合は、どの inode 領域とどのブロックが空であるかを知る必要があります。これには、それぞれ inode ビットマップを保存するために 1 つのブロックを使用し、ブロック ビットマップを保存するために 1 つのブロックを使用する必要があります。各ビットは、占有されている場合は 1、占有されていない場合は 0 です。ただし、ブロックには最大 4K*8=32K ビットが含まれており、最大 32K ブロックのステータスを表すことができるため、大規模なシステムを構築するには、これらのブロックをブロック グループに編成する必要があります。

ハードリンクとソフトリンク

ハード リンクは元のファイルと同じ inode を共有しますが、inode はファイル システムをまたぐことができないため、ハード リンクもファイル システムをまたぐことはできません。

ソフト リンクには独自の inode がありますが、ファイルが開かれると別のファイルを指すため、ファイル システムをまたいで元のファイルが削除されても存在し続ける可能性があります。

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。

以下もご興味があるかもしれません:
  • Linux環境でExt3ファイルシステムを使用する
  • Linux で lvm 論理ボリューム パーティションのサイズを調整するチュートリアル (xfs や ext4 などのさまざまなファイル システム用)
  • Linux ファイルシステムの説明: ext4 以降
  • Linux コマンドで mysqladmin Extended-status を使用して、Linux で MySQL の実行ステータスを表示します。

<<:  Vue プロジェクトで axios をカプセル化する方法 (http リクエストの統合管理)

>>:  Linuxターミナルでの一般的なMySQL操作コマンドの詳細な説明

推薦する

Linux を使用して時間指定ファイルが占有するディスク容量を計算する方法

スケジュールされたタスク エディターを開きます。Cent は、デフォルトで vim を使用して直接開...

Docker 構成 Alibaba Cloud イメージアクセラレーション プル実装

今日はdockerを使ってイメージをpullしたのですが、速度が悪くて見れず最後まで待ち続けました。...

nginxアクセス制御の実装例

高性能で軽量なウェブサービスソフトウェアであるNginxについて高い安定性 システムリソースの消費量...

HTML+CSS で div タグの右上隅に削除アイコンを追加するサンプルコード

1. 要件の説明Divタグの右上隅に削除アイコンを表示します2. 実装html、CSS 3. 参照コ...

docker+jenkins+node.js の自動デプロイメント環境をゼロから構築する方法

このケースはCentOS 7システムに基づいていますDockerの使用経験がある人に適していますLi...

Webpack ファイル パッケージ化エラー例外

webpack をパッケージ化する前に、次の作業が完了していることを確認する必要があります。 1) ...

別の種類の「キャンセル」ボタン

「キャンセル」ボタンは必要な操作プロセスの一部ではなく、デザイン上の主要な要素として表示されません...

JavaScript データ型変換の例 (他の型を文字列、数値型、ブール型に変換する)

序文データ型変換とは何ですか?フォームまたはプロンプトを使用して取得されるデフォルトのデータ型は文字...

入力タイプ=ファイルスタイルを定義する方法

ファイルコントロールを美しくする理由は何ですか?他の子供たちはみんなきちんとしたきれいな服を着ている...

Vue ルーター vue-router 詳細説明ガイド

中国語ドキュメント: https://router.vuejs.org/zh/ Vue Router...

JavaScript 定期検証パスワード強度実装方法

展示する デザインパスワード強度分析パスワードは数字、文字、特殊記号で構成されていますパスワード: ...

Vueはキャンバスを使用して画像圧縮アップロードを実現します

この記事では、キャンバスを使用して画像圧縮アップロードを実現するVueの具体的なコードを参考までに共...

Vueはズームイン、ズームアウト、ドラッグ機能を実装しています

この記事では、参考までに、ズームインとズームアウトのドラッグ機能を実現するためのVueの具体的なコー...

ショートカットアイコンとアイコンコードの違いの紹介

ステートメント 1: <link rel="shortcut icon" ...

JavaScriptにおける評価戦略の詳細な説明

目次それを覆う栗パラメータの受け渡し値渡し共同配送要約する拡張機能 - 遅延評価私は最近、JavaS...