ユーザー空間ファイル システムをサポートするために使用される Linux カーネル モジュールは FUSE と呼ばれます。 Fuse の正式名は「Filesystem in Userspace」で、中国語で「ユーザー空間ファイル システム」を意味します。完全にユーザー モードで実装されたファイル システムを指します。Linux で特定のネットワーク スペースをマウントするために使用され、重要なコンポーネントです。一般的なオペレーティング システムのこと。
#このチュートリアルの動作環境: linux7.3 システム、Dell G3 コンピューター。
Linux Fuse とは
ユーザー空間ファイル システム (ユーザー空間のファイルシステム) は、ユーザー モードで完全に実装されたファイル システムを指します。 Linux SSH などの特定のネットワーク スペースをローカル ファイル システムにマウントするために使用されるモジュール 関連コンテンツは SourceForge にあります。
ユーザー空間ファイル システムをサポートするために Linux で使用されるカーネル モジュールは FUSE と呼ばれます。FUSE という用語は、特に Linux のユーザー空間ファイル システムを指す場合があります。これは、一般的なオペレーティング システムの重要な部分です。オペレーティング システムは従来、カーネル レベルでファイル システムのサポートを提供してきました。一般に、カーネル モード コードはデバッグが難しく、生産性が低くなります。
いわゆる「ユーザー モード ファイル システム」とは、ファイル システムのデータとメタデータがユーザー モード プロセス (このプロセスは「デーモン」と呼ばれます) によって提供されることを意味します。マイクロカーネル オペレーティング システムの場合、ユーザー モードでファイル システムを実装することは何もありませんが、マクロカーネル Linux の場合は意味が異なります。
ユーザーモードファイルシステムと呼ばれていますが、カーネルの関与を全く必要としないわけではありません。Linux では、ファイルへのアクセスは、提供されるカーネルインターフェースを通じて一律に行われます。 VFS レイヤー (オープン/読み取りなど) であるため、プロセス (「ユーザー」と呼ばれる) がデーモンによって実装されたファイル システムにアクセスするときも、VFS を経由する必要があります。
VFS がユーザー プロセスからファイル アクセス リクエストを受信し、そのファイルが (マウント タイプに従って) ユーザー モード ファイル システムに属していると判断すると、リクエストを「fuse」という名前のファイルに転送します。カーネルモジュール。そして、「fuse」はリクエストをデーモンと取り決めたプロトコル形式に変換し、デーモンプロセスに送信します。
この 3 者関係では、「ヒューズ」カーネル モジュールが転送の役割を果たし、VFS の確立に役立つことがわかります (また、平たく言えば、その役割は実際には「エージェント」です。
このフレームワーク全体の Linux での実装は、FUSE (ユーザー空間のファイルシステム) です。図 1 に示すように、赤枠の部分は FUSE タイプのファイル システムの具体的な実装であり、ユーザー モード ファイル システムの設計者が活躍できる領域です。現在、FUSE に基づいて実装されているファイル システムは 100 を超えています (一部のカーネル ベースのファイル システムは、ZFS や NTFS などのユーザー モード ファイル システムに移植することもできます)。この記事では既製の FUSE を使用します。デモンストレーション用の sshfs。
まず、fuse-sshfs ソフトウェア パッケージをインストールし、次のコマンドを使用してファイル システムをマウントします (リモート マシンの「remote-dir」ディレクトリをローカル マシンの「local-dir」ディレクトリにマウントします)。 :
sshfs:
その後、「/sys/fs」にディレクトリに「fuse」という名前のフォルダが生成され、同時に「fuse」カーネルモジュールがロードされていること(対応するデバイスは「/dev/fuse」)と、ローカルマウントの種類が確認できます。ディレクトリは「fuse.sshfs」になりました:
デバイス ノードを生成する目的は、ユーザー モードの制御を容易にすることですが、ファイル システム レベルのアプリケーションの場合は、ioctl() を使用します。詳細が多すぎるため、デバイスにアクセスするのはまだ面倒なので、libfuse が中間層として登場しました。デーモン プロセスは、実際には、libfuse が提供するインターフェイスを通じてヒューズ デバイス ファイルを操作します。
次に、例として「touch」コマンドを使用して「fuse.sshfs」ファイル システムに新しいファイルを作成し、ヒューズ カーネル モジュールとデーモン プロセス (つまり、「sshfs」) 固有の対話プロセス (コード部分はカーネル バージョン 5.2.0 に基づいています):
[最初のラウンド]
最初は次のとおりです。パーミッションの検証ですが、ここでの検証は VFS のパーミッションの検証と同等ではなく、主な目的は他のユーザーが自分のプライベート Fuse ファイル システムにアクセスできないようにすることです。
#次に、ファイル パスに基づいてファイルの i ノードが見つかります。これは新しく作成されたファイルであるため、inode はカーネルの i ノード キャッシュにないため、「検索」リクエストをデーモンに送信する必要があります。
これらのリクエストは、 pending queue に入れられ、デーモン プロセスの応答を待ち、ユーザー プロセスはスリープ状態になります:
デーモンとして、 sshfs プロセスは、データを取得するために「/dev/fuse」デバイス ファイルを読み取ります。保留中のキューが空の場合、ブロック待機状態になります。
リクエストが保留中のキューがあると、デーモン プロセスが起動され、これらの要求を処理します。処理されたリクエストは 処理キュー に移動されます。デーモン プロセスがフューズ カーネル モジュールに応答した後、ユーザー プロセスが起動され、対応するリクエストが処理キューから削除されます。
【第2ラウンド】
次は「タッチ」です。トリガーされた他のシステム コールが以前にアクセスされたデータ/メタデータである場合、それらはキャッシュ内に存在する可能性が高く、データ/メタデータのこの部分に再度アクセスすると、ヒューズ カーネル モジュールは、それ以外の場合は、処理のためにデーモン プロセスに報告する必要があります。
ここで get_fuse_conn() は、ヒューズ型ファイル システムのマウント時に作成される "fuse_conn" 構造体インスタンスを取得します。デーモン プロセスとカーネル間のリンクとして、デーモン プロセスが停止するか、対応するヒューズ ファイル システムがアンインストールされない限り、接続は常に存在します。
デーモンプロセス側では、同様の操作がまだあります。注意する必要があるのは、2 つの一連の関数 furuse_write/read() と fuse_dev_write/read() の違いです。前者は、ユーザー プロセスがファイルにアクセスするときの VFS です。ヒューズ ファイル システム。読み取りおよび書き込みリクエストは通常のファイルに対する操作であり、後者は、ヒューズ カーネル モジュールを表すデバイス "/dev/fuse" の読み取りおよび書き込みを行うデーモン プロセスです。目的は、リクエストを取得し、返事。
[第 3 ラウンド ]
ヒューズ カーネル モジュールとデーモン プロセス間の対話の最後のラウンドは、ヒューズ ファイル システム スーパーブロック内の i ノード番号を取得し、このメタデータの関連情報を入力します。
比較的単純な「タッチ」操作が実行された場合でも、ヒューズ ファイル システム内でそれを見つけるのは難しくありません。 、ユーザー状態が関係します。カーネル状態とカーネル状態の間の切り替えは比較的頻繁に行われ、複数のデータ コピーが伴います。従来のカーネル ファイル システムと比較すると、全体的な I/O スループットが低く、待ち時間が長くなります。
では、なぜヒューズはオペレーティング システムでサポートされているファイル システム内で依然として重要な位置を占めているのでしょうか?そういえば、ユーザーモードでの開発には多くの利点があります。 まず、 はデバッグが簡単で、特に新しいファイル システム プロトタイプの迅速な検証に適しているため、学術研究の分野で非常に人気があります。カーネルではC言語のみ使用可能ですが、ユーザーモードではそれほど制限はなく、各種関数ライブラリや各種プログラミング言語が使用可能です。
2 つ目、 カーネルのバグは、わずかな不一致でシステム全体のクラッシュを引き起こすことがよくあります (ホストのクラッシュにより、ホスト上で実行されているすべての仮想マシンが引き起こされるため、これは仮想化アプリケーションではより深刻です)ただし、ユーザー モードのバグによる影響は比較的限定的です。
つまり、コインの表側は開発に便利であるということですが、それがどれほど便利であるかは結局のところ 主観的なの感覚であり、裏側はパフォーマンスへの影響です。使用できるもの目的は実験データによって検証されています。では、ヒューズによる損失を比較的正確に測定するにはどのような方法を使用すればよいでしょうか?
以前使用していたfuse-sshfsを引き続き使用しますが、ここではリモート マウントを使用せず、ローカル マウントを使用します(ローカル マシンの "dir-src" ディレクトリが ext4 ファイル システムにあると仮定します) ):
sshfs localhost:
デーモン プロセスがリクエストを受信すると、再度カーネルに入る必要があります。 ext4 カーネル モジュールにアクセスするには (このファイル システム モードは「スタッカブル」と呼ばれます):
ヒューズ ファイル システムに write() リクエストを発行するユーザー プロセスを次のようにします。例として、右側の赤いボックスはネイティブの ext4 呼び出しパスで、左側の追加のパスはヒューズの導入後に追加されたパスです。
# によると#この記事 ドキュメントに記載されているデータによると、このシステム コールで使用される「getxattr」によって形成されるリクエストには、「ユーザーとカーネル」の対話量の 2 倍が必要です。 シーケンシャル書き込みの場合、ネイティブ ext4 ファイル システムと比較して、I/O スループットは 27% 減少し、ランダム書き込みは 44% 減少します。
しかし、ヒューズ ファイル システムが誕生してから何年もの間、誰もがそれに対する多くの最適化策を考え出してきました。たとえば、順次読み取りと書き込みを行う場合、リクエストをバッチでデーモン プロセスに送信するように設計できます (ただし、ランダムな読み取りと書き込みは適していません)。スプライシング このゼロコピー テクノロジ、つまり Linux カーネルによって提供されるスプライシング メカニズムを使用すると、ユーザー空間は 2 つのカーネルのメモリ バッファのデータをコピーせずに転送できます。したがって、ヒューズ カーネル モジュールから ext4 カーネル モジュールにデータを直接転送するスタッカブル モードに特に適しています (ただし、スプライシングは通常 4K を超えるリクエストに使用され、少量のデータの読み書きには使用されません)。
これらの取り組みの後、Fuse ファイル システムはどのようなパフォーマンスを達成できるでしょうか? Android v4.4 から v7.0 の間に存在した SDcard デーモンから、近年の Ceph および GlusterFS まで、すべてが FUSE ベースの実装を採用しているか、現在採用中です。 FUSE は、ネットワーク ファイル システムと仮想化アプリケーションの両方でその有用性を示しています。その出現と発展は、カーネル モードで実装されたファイル システムを置き換えるものではなく、有用な補足としてのものです (理論的には、FUSE はルート ファイル システムの実装にも使用できますが、これはお勧めできません。「できる」と「するべき」は別のことです)。 関連する推奨事項: 「Linux ビデオ チュートリアル 」
以上がLinux ヒューズとはどういう意味ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。