詳細な記事:Linuxファイルシステムの分析

ここに画像の説明を挿入
Linuxファイルシステムアーキテクチャは、複雑なシステムを抽象化する興味深い例です。Linuxは、一般的なAPI関数のセットを使用することにより、さまざまな種類のストレージデバイスでさまざまな種類のファイルシステムをサポートできます。たとえば、read関数呼び出しは、指定されたファイル記述子から特定のバイト数を読み取ることができます。

読み取り機能は、ext3やNFSなどのファイルシステムのタイプを認識していません。また、ATアタッチメントパケットインターフェイス(ATAPI)ディスク、シリアル接続SCSI(SAS)ディスク、シリアルアドバンストテクノロジーアタッチメント(SATA)ディスクなど、ファイルシステムが配置されているストレージメディアも認識しません。

ただし、read関数を呼び出してファイルを読み取ると、データは正常に返されます。この記事では、このメカニズムを実装する方法を説明し、Linuxファイルシステム層の主な構造を紹介します。

ビデオ分析:

Linuxカーネルインタビューの30の質問を含む、Linuxカーネルファイルシステムの特定の実装とカーネル調整、およびLinuxカーネルファイルシステム
の実装について説明します。

ファイルシステムとは何ですか?

最も一般的な質問である「ファイルシステムとは」に最初に答えてください。ファイルシステムは、ストレージデバイス上のデータとメタデータを整理するためのメカニズムです。定義が非常に広いので、それをサポートするコードは興味深いでしょう。前述のように、ファイルシステムとメディアには多くの種類があります。非常に多くの種類があるため、Linuxファイルシステムインターフェイスは、ユーザーインターフェイス層、ファイルシステム実装、およびストレージデバイスを操作するドライバーを分離する階層化アーキテクチャとして実装されることが期待できます。

マウント
Linuxでファイルシステムをストレージデバイスに関連付けるプロセスは、マウントと呼ばれます。mountコマンドを使用して、ファイルシステムを現在のファイルシステム階層(ルート)にアタッチします。マウントを実行するときは、ファイルシステムの種類、ファイルシステム、およびマウントポイントを指定します。

Linuxファイルシステムレイヤーの機能(およびマウント方法)を説明するために、現在のファイルシステムのファイルにファイルシステムを作成します。これを実現する方法は、最初にddコマンドを使用して、指定したサイズのファイルを作成することです(ファイル・コピーのソースとして/ dev / zeroを使用します)。つまり、リスト1に示すように、ゼロで初期化されたファイルです。

リスト1.初期化されたファイルを作成する

$ dd if=/dev/zero of=file.img bs=1k count=10000
10000+0 records in
10000+0 records out
$

これで、10MBのfile.imgファイルができました。lostupコマンドを使用して、ループデバイスをこのファイルに関連付け、ファイルシステム内の通常のファイルではなくブロックデバイスのように見せます。

$ losetup /dev/loop0 file.img
$

このファイルは、ブロックデバイス(/ dev / loop0で表される)として表示されます。次に、mke2fsを使用して、このデバイス上にファイルシステムを作成します。このコマンドは、リスト2に示すように、指定されたサイズの新しいext2ファイルシステムを作成します。

リスト2.ループデバイスを使用したext2ファイルシステムの作成

$ mke2fs -c /dev/loop0 10000
mke2fs 1.35 (28-Feb-2004)
max_blocks 1024000, rsv_groups = 1250, rsv_gdb = 39
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
2512 inodes, 10000 blocks
500 blocks (5.00%) reserved for the super user
...
$

mountコマンドを使用して、ループデバイス(/ dev / loop0)で表されるfile.imgファイルをマウントポイント/ mnt / point1にマウントします。ファイルシステムタイプはext2として指定されていることに注意してください。マウント後、リスト3に示すように、たとえばlsコマンドを使用して、このマウントポイントを新しいファイルシステムとして使用できます。

リスト3.ループデバイスを介してマウントポイントを作成し、ファイルシステムをマウントする

$ mkdir /mnt/point1
$ mount -t ext2 /dev/loop0 /mnt/point1
$ ls /mnt/point1
lost+found
$

リスト4に示すように、プロセスを続行できます。マウントしたばかりのファイルシステムに新しいファイルを作成し、それをループデバイスに関連付けて、その上に別のファイルシステムを作成します。

リスト4.循環ファイルシステムでの新しい循環ファイルシステムの作成

$ dd if=/dev/zero of=/mnt/point1/file.img bs=1k count=1000
1000+0 records in
1000+0 records out
$ losetup /dev/loop1 /mnt/point1/file.img
$ mke2fs -c /dev/loop1 1000
mke2fs 1.35 (28-Feb-2004)
max_blocks 1024000, rsv_groups = 125, rsv_gdb = 3
Filesystem label=
...
$ mkdir /mnt/point2
$ mount -t ext2 /dev/loop1 /mnt/point2
$ ls /mnt/point2
lost+found
$ ls /mnt/point1
file.img lost+found
$

この簡単なデモンストレーションを通して、Linuxファイルシステム(およびループデバイス)がいかに強力であるかを理解するのは簡単です。同じ方法を使用して、循環デバイスを使用してファイル上に暗号化されたファイルシステムを作成できます。ループデバイスを使用して、必要に応じてファイルを一時的にマウントできます。これにより、データを保護できます。

[記事のメリット] C / C ++ Linuxサーバーアーキテクトの学習資料とグループ812855908(C / C ++、Linux、golangテクノロジー、Nginx、ZeroMQ、MySQL、Redis、fastdfs、MongoDB、ZK、ストリーミングメディア、CDN、P2P、K8S、 Docker、TCP / IP、coroutine、DPDK、ffmpegなど)
ここに画像の説明を挿入

ファイルシステムのアーキテクチャファイルシステム
の構築方法を見てきたので、Linuxファイルシステム層のアーキテクチャを見てみましょう。この記事では、Linuxファイルシステムを2つの観点から検討します。まず、高レベルのアーキテクチャの観点を採用します。次に、詳細な議論を続け、ファイルシステム層の主な構造を紹介します。

高レベルのアーキテクチャ
ほとんどのファイルシステムコードはカーネル内にありますが(後で説明するユーザースペースファイルシステムを除く)、図1に示すアーキテクチャは、ユーザースペースとカーネル内のメインファイルシステム関連コンポーネントとの関係を示しています。 。

図1.Linuxファイルシステムコンポーネントのアーキテクチャ。
ここに画像の説明を挿入
ユーザースペースには、いくつかのアプリケーション(ファイルシステムのユーザーなど)と、ファイルシステム呼び出し(オープン、読み取り、書き込み、およびファイルシステム呼び出し)をユーザーに提供するGNU Cライブラリ(glibc)が含まれています。 close)インターフェイス。システムコールインターフェイスは、ユーザースペースからカーネルスペースの適切なエンドポイントにシステムコールを送信するスイッチのように機能します。

VFSは、基盤となるファイルシステムのメインインターフェイスです。このコンポーネントは、一連のインターフェースをエクスポートしてから、それらをさまざまなファイルシステムに抽象化します。各ファイルシステムの動作は大きく異なる場合があります。ファイルシステムオブジェクトには2つのキャッシュ(inodeとdentry)があります。最近使用したファイルシステムオブジェクトをキャッシュします。

各ファイルシステム実装(ext2、JFSなど)は、VFSで使用するための共通インターフェイスのセットをエクスポートします。バッファキャッシュは、ファイルシステムと関連するブロックデバイス間の要求をキャッシュします。たとえば、基になるデバイスドライバーへの読み取りおよび書き込み要求は、バッファーキャッシュを介して渡されます。これにより、リクエストをキャッシュできるようになり、物理デバイスへのアクセス数が減り、アクセスが高速化されます。バッファキャッシュは、最近使用された(LRU)リストの形式で管理されます。syncコマンドを使用して、バッファーキャッシュ内の要求をストレージメディアに送信できることに注意してください(書き込まれていないすべてのデータをデバイスドライバーに送信してから、ストレージデバイスに送信するように強制します)。

これは、VFSおよびファイルシステムコンポーネントの高レベルの状況です。ここで、このサブシステムの実現の主な構造について説明します。


Linuxの主な構造は、一連の共通オブジェクトの観点からすべてのファイルシステムを調べます。これらのオブジェクトは、スーパーブロック、iノード、dentry、およびファイルです。スーパーブロックは、各ファイルシステムのルートにあります。スーパーブロックは、ファイルシステムの状態を記述および維持します。ファイルシステムで管理される各オブジェクト(ファイルまたはディレクトリ)は、Linuxではiノードとして表されます。iノードには、ファイルシステム内のオブジェクトを管理するために必要なすべてのメタデータが含まれています(オブジェクトに対して実行できる操作を含む)。

別の構造のセットはdentryと呼ばれ、名前とiノード間のマッピングを実装するために使用されます。最近使用されたdentryを格納するためのディレクトリキャッシュがあります。Dentryは、ファイルシステムでの移動をサポートするために、ディレクトリとファイル間の関係も維持します。最後に、VFSファイルは開いているファイルを表します(書き込みオフセットなど、開いているファイルの状態を保存します)。

仮想ファイルシステムレイヤー
VFSは、ファイルシステムインターフェイスのルートレイヤーとして機能します。VFSは、現在サポートされているファイルシステムと現在マウントされているファイルシステムを記録します。

一連の登録関数を使用して、Linuxでファイルシステムを動的に追加または削除できます。カーネルは、現在サポートされているファイルシステムのリストを保存します。これは、/ procファイルシステムを介してユーザースペースで表示できます。この仮想ファイルには、これらのファイルシステムに現在関連付けられているデバイスも表示されます。Linuxで新しいファイルシステムを追加する方法は、register_filesystemを呼び出すことです。この関数のパラメーターは、ファイルシステム構造(file_system_type)への参照を定義します。これは、ファイルシステムの名前、属性のセット、および2つのスーパーブロック関数を定義します。ファイルシステムからログオフすることもできます。

新しいファイルシステムを登録すると、ファイルシステムとその関連情報がfile_systemsリストに追加されます(図2およびlinux / include / linux / mount.hを参照)。このリストは、サポートできるファイルシステムを定義します。このリストを表示するには、コマンドラインでcat / proc / filesystemsと入力します。

図2.カーネルに登録されているファイルシステム
画像
。VFSで維持されているもう1つの構造は、マウントされたファイルシステムです(図3を参照)。この構造は、現在マウントされているファイルシステムを提供します(linux /include/linux/fs.hを参照)。これは、以下で説明するスーパーブロック構造にリンクしています。

図3.マウントされたファイルシステムのリスト
画像
スーパーブロック
スーパーブロック構造は、ファイルシステムを表します。これには、ファイルシステム名(ext2など)、ファイルシステムのサイズとステータス、ブロックデバイス参照、メタデータ情報(フリーリストなど)など、ファイルシステムの管理に必要な情報が含まれています。スーパーブロックは通常、ストレージメディアに保存されますが、スーパーブロックが存在しない場合は、リアルタイムで作成することもできます。スーパーブロック構造は./linux/include/linux/fs.hにあります(図4を参照)。

図4.スーパーブロック構造とiノード操作
ここに画像の説明を挿入

スーパーブロックの重要な要素は、スーパーブロック操作の定義です。この構造は、このファイルシステムでiノードを管理するために使用される一連の関数を定義します。たとえば、alloc_inodeを使用してiノードを割り当て、destroy_inodeを使用してiノードを削除できます。read_inodeとwrite_inodeを使用してiノードの読み取りと書き込みを行い、sync_fsを使用してファイルシステムの同期を実行できます。super_operations構造体は、。/ linux / include / linux /fs.hにあります。各ファイルシステムは、操作を実装し、VFSレイヤーに共通の抽象化を提供する独自のiノードメソッドを提供します。


iノードおよびdentryiノードは、一意の識別子を持つファイルシステム内のオブジェクトを表します。各ファイルシステムは、ファイル名を一意のiノード識別子およびiノード参照にマップする方法を提供します。

図5は、iノード構造の一部と2つの関連する構造を示しています。inode_operationsとfile_operationsに特に注意してください。これらの構造は、このiノードで実行できる操作を表しています。inode_operationsは、inodeで直接実行される操作を定義し、file_operationsは、ファイルとディレクトリに関連するメソッド(標準のシステムコール)を定義します。

図5.iノードの構造と関連する操作
ここに画像の説明を挿入

iノードとディレクトリキャッシュはそれぞれ、最近使用されたiノードとdentryを格納します。iノードキャッシュ内の各iノードについて、ディレクトリキャッシュ内に対応するdentryがあることに注意してください。iノードおよびdentryの構造は、。/ linux / include / linux /fs.hにあります。

バッファキャッシュ
さまざまなファイルシステムの実装(./linux/fsにあります)に加えて、ファイルシステム層の最下部はバッファキャッシュです。このコンポーネントは、ファイルシステムの実装および物理デバイスからの読み取りおよび書き込み要求を(デバイスドライバーを介して)追跡します。効率を向上させるために、Linuxは要求をキャッシュして、すべての要求が物理デバイスに送信されないようにします。最近使用されたバッファ(ページ)はキャッシュにキャッシュされ、これらのバッファはさまざまなファイルシステムにすばやく提供できます。

興味深いファイルシステム
この記事では、Linuxで使用できる特定のファイルシステムについては説明していませんが、ここで言及する価値があります。Linuxは、MINIX、MS-DOS、ext2などの古いファイルシステムを含む多くのファイルシステムをサポートしています。Linuxは、ext3、JFS、ReiserFSなどの新しいジャーナルファイルシステムもサポートしています。さらに、Linuxは暗号化されたファイルシステム(CFSなど)と仮想ファイルシステム(/ procなど)をサポートしています。

最後の注目すべきファイルシステムは、Filesystem in Userspace(FUSE)です。このファイルシステムは、VFSを介してファイルシステム要求をユーザースペースに送り返すことができます。したがって、独自のファイルシステムを作成することに興味がある場合は、FUSEを使用して開発することをお勧めします。

結びの言葉

ファイルシステムの実装は複雑ではありませんが、スケーラブルで拡張可能なアーキテクチャの良い例です。ファイルシステムアーキテクチャは長年にわたって開発されており、さまざまな種類のファイルシステムと多くのターゲットストレージデバイスの種類をサポートしてきました。プラグインベースのアーキテクチャと多層機能の間接性により、Linuxファイルシステムの最近の開発は注目に値します。

公式アカウントに注意を払い、興味のあるインターネット技術コンテンツをもっと共有してください!
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_40989769/article/details/111754861