Linuxオペレーティングシステムの研究ノート(11)ファイルシステム

I.はじめに

  このセクションの冒頭では、Linuxファイルシステムを分析します。すべてがLinuxのファイルであるという考えはよく知られており、そのファイルシステムはキャラクターデバイス、ブロックデバイス、パイプ、プロセス間通信、ネットワークなどに不可欠な知識であるため、その重要性は想像できます。この記事では、最初にファイルシステムの基本を紹介し、次に最も重要な構造inodeとその上に構築された階層化ファイルシステムを紹介します。

2.ファイルシステムの基本的な知識

  すべてが要件を満たすように設計されているため、ファイルシステムに必要な基本機能から設計する方法を検討します。まず、ファイルシステムには次の基本的な要件が必要です。

  • ファイルは読み書きが簡単で、名前の競合などを回避する必要があります。
  • ファイルは簡単に見つけ、整理し、分類する必要があります
  • オペレーティングシステムには、管理用のドキュメント機能が必要です。

  したがって、ファイルシステムは次の特性で設計されています。

  • ツリー構造とフォルダー設計を採用
  • 読み書きが簡単なホットファイルをキャッシュする
  • インデックス構造を使用して、分類を見つけやすい
  • 一連のデータ構造を維持して、どのドキュメントがどのタスクで使用されているかを記録する

  この基本設計に基づいて、Linuxの広範でスピリチュアルなファイルシステムをゆっくりと検討し始めることができます。

3. iノードの構造とファイルシステム

3.1ブロックストレージの表現

  ハードディスクではブロックを記憶単位として使用しますが、ファイルシステムではブロック情報を格納するための基本的な構造が必要です。これがファイルシステムinodeの要です。ソースコードは次のとおりです。inodeそれはindex nodeそのインデックスノードを意味します。このデータ構造から、inodeファイルの読み取りと書き込みの権限i_mode、ユーザーが所属するi_uidグループi_gidグループ、サイズi_size_lo、およびブロックの数がわかりますi_blocks_loさらに、ファイルに関連するいくつかの回があります。i_atimeこれaccess timeは、ファイルへの最後のアクセスの時刻です。i_ctimeつまりchange time、最新の変更inode時刻です。i_mtimeつまりmodify time、ファイルの変更が最後の時刻です。

/*
 * Structure of an inode on the disk
 */
struct ext4_inode {
    
    
    __le16	i_mode;		/* File mode */
    __le16	i_uid;		/* Low 16 bits of Owner Uid */
    __le32	i_size_lo;	/* Size in bytes */
    __le32	i_atime;	/* Access time */
    __le32	i_ctime;	/* Inode Change time */
    __le32	i_mtime;	/* Modification time */
    __le32	i_dtime;	/* Deletion Time */
    __le16	i_gid;		/* Low 16 bits of Group Id */
    __le16	i_links_count;	/* Links count */
    __le32	i_blocks_lo;	/* Blocks count */
    __le32	i_flags;	/* File flags */
......
    __le32	i_block[EXT4_N_BLOCKS];/* Pointers to blocks */
......
};

#define EXT4_NDIR_BLOCKS 12
#define EXT4_IND_BLOCK EXT4_NDIR_BLOCKS
#define EXT4_DIND_BLOCK (EXT4_IND_BLOCK + 1)
#define EXT4_TIND_BLOCK (EXT4_DIND_BLOCK + 1)
#define EXT4_N_BLOCKS (EXT4_TIND_BLOCK + 1)

  ここでは、以下に焦点を当てる必要i_blockがあります。メンバー変数は、実際にはファイルコンテンツの各ブロックを格納します。ext2およびext3形式のファイルシステムでは、最初の12ブロックを使用して対応するファイルデータを保存します。各ブロックは4KBです。ファイルが大きすぎて収まらない場合は、次のいくつかの間接ストレージブロックを使用してデータを保存する必要があります。その貯蔵原理の鮮やかな表現。

img

  このストレージ構造の問題は、大きなファイルの場合、対応するブロックのコンテンツにアクセスするために複数の呼び出しが必要になるため、アクセス速度が遅いことです。このため、ext4は新しいソリューションであるExtentsを提案しました簡単に言えば、エクステントはツリー構造を使用してファイルブロックを継続的に格納し、アクセス速度を向上させます。一般的な構造を次の図に示します。

[外部リンク画像の転送に失敗しました。ソースサイトにアンチリーチリンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-lB3a7yLE-1596126703207)(https://ars.els-cdn.com/content/image/1-s2 .0-S1742287617300270-gr2.jpg)]

  主な構造はノードext4_extent_headerでありeh_entries、このノードにあるアイテムの数示します。ここには2種類のアイテムがあります。

  • リーフノードの場合、この項目は、ハードディスク上の連続したブロックのアドレスを直接指しますext4_extentこれは、データノードと呼ばれます
  • ブランチノードの場合、このアイテムは次のレイヤーのブランチノードまたはリーフノードを指しますext4_extent_idxこれをインデックスノードと呼びますこの2種類のアイテムのサイズは12 byteです。

  ファイルが小さい場合は、inode内側i_blockに1 ext4_extent_headerと4を付けext4_extentます。したがって、今回eh_depthは0でinode、葉ノードがあり、木の高さは0です。ファイルが大きく、4つextentが収まらないeh_depth>0場合は、ツリーに分割する必要があります。ノードはiノードであり、inode中間のルートノードの最大深度です下部eh_depth=0はリーフノードです。ルートノードに加えて、他のノードは4k、4k ext4_extent_headerの12の控除内のブロックに保存されbyte、残りは340を置くことができ、それぞれextent最大128MBのデータを表すことができ、340 extentは42.5GBに到達したファイルを示します。これはすでに非常に大きいです。大きい場合、ツリーの深さを増やすことができます。

/*
 * Each block (leaves and indexes), even inode-stored has header.
 */
struct ext4_extent_header {
    
    
    __le16	eh_magic;	/* probably will support different formats */
    __le16	eh_entries;	/* number of valid entries */
    __le16	eh_max;		/* capacity of store in entries */
    __le16	eh_depth;	/* has tree real underlying blocks? */
    __le32	eh_generation;	/* generation of the tree */
};

/*
 * This is the extent on-disk structure.
 * It's used at the bottom of the tree.
 */
struct ext4_extent {
    
    
    __le32  ee_block;  /* first logical block extent covers */
    __le16  ee_len;    /* number of blocks covered by extent */
    __le16  ee_start_hi;  /* high 16 bits of physical block */
    __le32  ee_start_lo;  /* low 32 bits of physical block */
};

/*
 * This is index on-disk structure.
 * It's used at all the levels except the bottom.
 */
struct ext4_extent_idx {
    
    
    __le32  ei_block;  /* index covers logical blocks from 'block' */
    __le32  ei_leaf_lo;  /* pointer to the physical block of the next *
         * level. leaf or next index could be there */
    __le16  ei_leaf_hi;  /* high 16 bits of physical block */
    __u16  ei_unused;
};

  したがって、inode一連のブロックを表現してファイルを形成できます。ハードディスクには、シリーズを通して、inode多数のファイルを保存することができます。しかし、それでもなお、保存および管理する方法が必要inodeです。これはビットマップです。同様に、ブロック情報を管理するためにブロックビットマップを使用します。以下はinode作成プロセス中のビットマップへのアクセスを示しています。次の0ビットがどこにあるか、つまり空きinode位置を見つける必要があります

struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
             umode_t mode, const struct qstr *qstr,
             __u32 goal, uid_t *owner, __u32 i_flags,
             int handle_type, unsigned int line_no,
             int nblocks)
{
    
    
......
    inode_bitmap_bh = ext4_read_inode_bitmap(sb, group);
......
    ino = ext4_find_next_zero_bit((unsigned long *)
                inode_bitmap_bh->b_data,
                EXT4_INODES_PER_GROUP(sb), ino);
......
}

3.2ファイルシステムフォーマット

  inodesumブロックはファイルシステムの最小単位であり、大まかに次のように、その上にマルチレベルシステムがあります。

  • ブロックグループ:データを格納する単位ext4_group_descデータ構造はです。inodeビットマップのグループ用のブロックbg_inode_bitmap_lo、ビットマップブロックbg_block_bitmap_lo対応する定義のinodeリストbg_inode_table_loがあります。各ブロックグループは、基本的にファイルシステム全体の構造を構成します。
  • ブロックグループ記述子テーブル:複数のブロックグループ記述子で構成されるテーブル
  • スーパーブロック:ファイルシステム全体が記述される場合、つまりext4_super_block、ファイルシステム全体などのグローバル情報を格納する場合の総数inode:; s_inodes_countブロックの総数:s_blocks_count_lo各ブロックグループ番号inodes_inodes_per_groupブロックグループのブロック数:s_blocks_per_groupその他。
  • ブートブロック:ファイルシステム全体で、オペレーティングシステムの起動用のブート領域として領域を予約する必要があるため、ブート領域を開始するには、最初のブロックグループの前に1Kを予約する必要があります。
img

  スーパーブロックおよびブロックグループ記述子テーブルはグローバル情報であり、これらのデータは非常に重要です。これらのデータが失われると、ファイルシステム全体を開くことができなくなります。これは、ファイルの1つのブロックの損傷よりも深刻です。したがって、これら2つの部分をバックアップする必要がありますが、戦略は異なります。

  • デフォルトの戦略:各ブロックにスーパーブロックとブロックグループの説明テーブルのコピーを保存します
  • sparse_super戦略:スパースストレージが採用され、0、3、5、7のブロックグループインデックスの整数乗でのみ保存されます。
  • メタブロックグループ戦略:ブロックグループを複数のメタブロックグループ(メタブロックグループ)に分割します。各メタブロックグループのブロックグループ記述子テーブルには、独自のコンテンツのみが含まれます。タプルグループには64個のブロックグループが含まれます。このようなタプルグループのブロックグループ記述子テーブルには、最大64項目があります。このアプローチは似てmerkle treeおり、スペースを大幅に最適化できます。
img

3.3ディレクトリの保存形式

  ファイルの検索を容易にするために、インデックス、つまりファイルディレクトリが必要です。実際、ディレクトリ自体もファイルですinodeinodeまた、いくつかのブロックを指しています。通常のファイルとは異なり、通常のファイルのブロックはファイルデータを格納し、ディレクトリファイルのブロックはディレクトリ内のファイル情報を項目ごとに格納します。これを情報と呼びますext4_dir_entry2番目のバージョンにext4_dir_entry_2は16ビットの2つのバージョンがありname_len、8ビットname_lenと8 ビットになりますfile_type

struct ext4_dir_entry {
    
    
    __le32  inode;      /* Inode number */
    __le16  rec_len;    /* Directory entry length */
    __le16  name_len;    /* Name length */
    char  name[EXT4_NAME_LEN];  /* File name */
};
struct ext4_dir_entry_2 {
    
    
    __le32  inode;      /* Inode number */
    __le16  rec_len;    /* Directory entry length */
    __u8  name_len;    /* Name length */
    __u8  file_type;
    char  name[EXT4_NAME_LEN];  /* File name */
};

  ブロックカタログファイルで、リストを保存する最も簡単な形式ext4_dir_entry_2。つまり、列ごとに1つずつ各アイテムは、ディレクトリの次のレベルにあるファイルのファイル名を保存します。inodeこれinodeにより、実際のファイルを見つけることができます。最初の項目は「。」で現在のディレクトリを示し、2番目の項目は「...」で上位レベルのディレクトリを示し、次はファイル名と項目inodeです。場合によっては、ディレクトリにファイルが多すぎる場合、このディレクトリでファイルを検索する必要がありますが、リストに従って1つずつ検索するのは遅すぎるため、インデックスモードを追加します。フラグinode設定するEXT4_INDEX_FLと、ファイルディレクトリ構成のブロックが変更され、以下のように定義されます。

struct dx_root
{
    
    
    struct fake_dirent dot;
    char dot_name[4];
    struct fake_dirent dotdot;
    char dotdot_name[4];
    struct dx_root_info
    {
    
    
      __le32 reserved_zero;
      u8 hash_version;
      u8 info_length; /* 8 */
      u8 indirect_levels;
      u8 unused_flags;
    }
    info;
    struct dx_entry  entries[0];
};

  現在のディレクトリと親ディレクトリは変更されず、ファイルリストはdx_root_info構造に変更されます。最も重要なメンバー変数は、間接的なインデックスレベルの数を示すindirect_levelsです。dx_entry表現される構造によるインデックスエントリ、マッピング関係は、ファイル名とデータブロックのハッシュ値です。

struct dx_entry
{
    
    
    __le32 hash;
    __le32 block;
};

  ディレクトリの下でファイル名を検索する場合は、名前でハッシュを取得できます。ハッシュが一致する場合、このファイルの情報が対応するブロックにあることを意味します。次に、インデックスがないがインデックスツリーのリーフノードである場合、このブロックを開きext4_dir_entry_2ます。行にファイル名が見つかる限り、リストは1つずつあります。インデックスツリーを使用すると、ディレクトリ内のN個を超えるファイルを多くのブロックに分散させることができ、すばやく検索できます。

img

3.4ソフトリンクとハードリンクの保存形式

  ソフトリンクとハードリンクも一種のファイルで、以下のコマンドで作成できます。ハードリンクを作成ln -sせずに、ソフトリンクを作成します-s

ln [参数][源文件或目录][目标文件或目录]

  ハードオリジナルのファイル共有Aへのリンクinodeが、inode各ファイルシステムは、独自の持っている、クロスファイルシステムではありませんinode、ファイルシステムにまたがるハードリンクに方法はありませんリストを、。ソフトリンクとは異なり、ソフトリンクはファイルの再作成と同等です。このファイルも独立していますがinode、このファイルを開いて内部のコンテンツを表示すると、コンテンツは別のファイルを指しています。これは非常に柔軟です。ファイルシステムをまたぐことができます。ターゲットファイルが削除されても、リンクされたファイルは存在しますが、指定されたファイルは見つかりません。

img

4.まとめ

  この記事は、主にファイルシステムの設計の視点から始まり、inodeそれに基づいinodeext4ファイルシステム構造と主要コンポーネントを徐々に分析しています。以下は、Geek Timeでの画像の要約です。

img

ソース情報

[1] iノード

[2] ext4_inode

[3] ext4_extent

参照

[1]ウィキ

[2] elixir.bootlin.com/linux

[3] woboq

[4] Linuxインサイド

[5] Linuxカーネルに対する深い理解

[6] Linuxカーネル設計の芸術

[7] Geek TimeがLinuxオペレーティングシステムについて語る

おすすめ

転載: blog.csdn.net/u013354486/article/details/107704439