Linux 仮想ファイルシステム・スイッチの徹底調査

抽象化とその大局的概念

Linux® が持つ柔軟性と拡張性は、まさに柔軟性と拡張性の定義そのものです。仮想ファイルシステム・スイッチ (VFS) を例に取っても、従来のディスクから USB フラッシュ・ドライブ、そしてメモリーやその他のストレージ・デバイスに至るまで、多種多様なデバイスでファイルシステムを作成することができます。さらに、ファイルシステムを別のファイルシステムのコンテキストに組み込むことさえ可能です。この記事を読んで、何が VFS をそれほど強力にしているのかを知り、その主要なインターフェースとプロセスについて学びましょう。

M. Tim Jones (mtj@mtjones.com), Independent author

M. Tim JonesM. Tim Jones は組み込みソフトウェアのエンジニアであり、『Artificial Intelligence: A Systems Approach』、『GNU/Linux Application Programming』(現在、第 2 版です) や『AI Application Programming』(こちらも現在、第 2 版です)、それに『BSD Sockets Programming from a Multilanguage Perspective』などの著者でもあります。技術的な経歴は静止軌道衛星用のカーネル開発から、組み込みシステム・アーキテクチャーやネットワーク・プロトコル開発まで、広範にわたっています。また、コロラド州ロングモン所在のEmulex Corp. の顧問エンジニアでもあります。


developerWorks 貢献著者レベル

2009年 8月 31日

Linux ファイルシステムのサポートを柔軟かつ拡張可能にしているのは、抽象化された一連のインターフェースそのものです。そしてこれらのインターフェースのコアとなっているのが、仮想ファイルシステム・スイッチ (VFS) です。

VFS は、上位層のアプリケーションが各種のファイルシステムでファイル入出力を行うための標準インターフェース一式を提供します。その提供の形は、ファイル入出力の対象となる 1 つ以上のデバイスに対して複数の並行するファイルシステムをサポートできるような形をとります。さらに、これらのファイルシステムは静的である必要はなく、ストレージ・デバイスの一時的な特徴に併せて動的に追加したり、削除したりすることも可能です。

仮想ファイルシステムなのか、それとも仮想ファイルシステム・スイッチなのか

VFS は仮想ファイルシステム (Virtual File System) としても定義されています。しかし、この層では複数のファイルシステム間で要求を切り替える (つまり多重化する) ことから、仮想ファイルシステム・スイッチ (Virtual File System Switch) と呼ぶほうが、遙かにその定義がわかりやすくなります。また、/proc ファイルシステムも一般に、仮想ファイルシステムと呼ばれることが、さらに混乱に拍車をかけています。

例えば、標準的な Linux デスクトップは使用可能なハード・ディスク上で ext3 ファイルシステムをサポートするだけでなく、CD-ROM が使用できるとしたら、CD-ROM 上で ISO 9660 ファイルシステムもサポートします (これは、CDFS (CD-ROM File System) とも呼ばれます)。CD-ROM は挿入された後に取り出されるため、Linux カーネルは構造と内容が異なる新しいファイルシステムに適応しなければなりません。リモート・ファイルシステムには、NFS (Network File System) を介してアクセスできるだけでなく、Linux はローカル・ハード・ディスクにある Windows®/Linux デュアルブート・システムの NTFS (NT File System) パーティションをマウントし、このパーティションに対して読み取り/書き込み操作を行うこともできます。

その上、リムーバル UFD (USB Flash Drive) のホットプラグも可能なことから、さらに別のファイルシステムまで提供される場合があります。これらのデバイスに対して常に、同じファイル入出力インターフェースのセットを使用できることから、そのベースとなるファイルシステムと物理デバイスをユーザーから抽象化できるというわけです (図 1 を参照)。

図 1. さまざまなファイルシステムとストレージ・デバイスに対して抽象化層が提供する統一されたインターフェース
さまざまなファイルシステムとストレージ・デバイスに対して抽象化層が提供する統一されたインターフェース

階層型抽象化

ここで、Linux VFS が提供する抽象化機能を具体的なアーキテクチャーで表してみます。図 2 は、VFS の観点から見た Linux スタックの概要図です。VFS の上にあるのは、標準カーネルのシステム・コール・インターフェース (SCI) で、このインターフェースによってユーザー空間から (別のアドレス空間にある) カーネルへと呼び出しを移行することができます。このドメインでは、ユーザー空間のアプリケーションが POSIX の open を呼び出すと、その呼び出しは GNU C ライブラリー (glibc) を介してカーネルへ渡されて、システム・コールの逆多重化が行われ、最終的には sys_open によって、VFS が呼び出されます。

図 2. VFS の階層型アーキテクチャー
VFS の階層型アーキテクチャー

以前の VFS の実装

共通ファイル・モデルをサポートするために仮想化層を採り入れたオペレーティング・システムは、Linux が最初ではありません。以前の VFS 実装には、Sun の VFS (1985年頃の SunOS バージョン 2)、IBM と Microsoft® の IBM OS/2 用「Installable File System」があります。ファイルシステム層に対するこれらの仮想化手法によって、Linux でも VFS が可能になりました。

VFS が提供する抽象化層は、特定のファイルシステムがその振る舞いをどのように実装しているかに関する詳細から POSIX API を切り離します。ここで鍵となるのは、そのベースにあるファイルシステムが ext3 であろうと Btrfs であろうと、API の open、read、write、または close といったシステム・コールは同じように機能することです。これは、ベースにあるファイルシステムが継承する共通ファイル・モデルを VFS が提供するからです (これらのファイルシステムは各種の POSIX API 関数に対する振る舞いを実装しなければなりません)。また、VFS外部でも抽象化が行われることで、さらにベースにある物理デバイスも隠されます (これらの物理デバイスはディスクであったり、ディスクのパーティション、ネットワーク接続されたストレージ・エンティティー、メモリー、あるいは情報を一時的であっても保存可能なその他の媒体であったりする場合があります)。

VFS は、ベースにあるファイルシステムに対するファイル操作の詳細を抽象化するだけでなく、同じくベースにあるブロック・デバイスと使用可能なファイルシステムとを結び付けます。ここからは、VFS の内部構造について、さらにはそれぞれがどのように機能するのかを見て行きます。


VFS の内部構造

VFS サブシステムの全体的なアーキテクチャーについて説明する前に、このサブシステムで使用される主要なオブジェクトについて説明しておきます。このセクションで取り上げるのは、スーパーブロック、索引ノード (inode)、ディレクトリー・エントリー (dentry)、そしてファイル・オブジェクトです。その他、キャッシュなどの重要な要素については、後ほど全体的なアーキテクチャーを説明するときに説明します。

スーパーブロック

スーパーブロックとはファイルシステムに関する上位レベルのメタデータを収容するコンテナーのことです。スーパーブロックは、ディスク上 (実際には、冗長性をもたらすためにディスク上の複数の部分) とメモリー内にその構造があり、ファイルシステムの管理パラメーター (ブロックの合計数、空きブロック、ルート inode など) を定義して、ディスク上のファイルシステムを処理するための基礎を提供します。

ディスク上のスーパーブロックは、ディスク上のファイルシステムの構造に関する情報をカーネルに提供します。メモリー内のスーパーブロックが提供するのは、アクティブな (マウントされた) ファイルシステムを管理するために必要な情報と状態です。Linux は同時にマウントされた複数の並行するファイルシステムをサポートするため、各 super_block 構造体は super_blocks リスト内に保持されます (super_blocks リストは ./linux/fs/super.c 内に定義され、/linux/include/fs/fs.h に定義された構造体を持ちます)。

図 3 は、スーパーブロックとその要素の概略図です。super_block 構造体は、他の情報をカプセル化する他の数多くの構造体を参照します。file_system_type 構造体は、例えばファイルシステムの名前 (ext3 など) や、super_block を取得および削除するための各種のロックおよび関数を保持します。file_system_type オブジェクトは、お馴染みの register_file システム関数と unregister_file システム関数 (./linux/fs/file systems.c を参照) を使用して管理されます。super_operations 構造体は、inode の読み取り/書き込み操作用の関数に加え、それより上位レベルの操作 (再マウントなど) を対象とした多数の関数を定義します。ルート dentry オブジェクトも、このファイルシステムが常駐するブロック・デバイスであることから同じくここにキャッシュされます。さらに、inode を管理するための多数のリストも提供されています。具体的には、s_inodes (すべての inode のリスト)、s_dirty (すべてのダーティー inode のリスト)、s_ios_more_io (ライトバック用に配置)、および s_files (特定のファイルシステム用に開かれているすべてのファイルのリスト) などのリストです。

図 3. super_block 構造体とその関連要素の概略図
super_block 構造体とその関連要素の概略図

カーネル内部では、vfsmount という別の管理オブジェクトが、マウントされたファイルシステムに関する情報を提供することに注意してください。これらのオブジェクトのリストはスーパーブロックを参照し、マウント・ポイント、このファイルシステムが常駐する /dev デバイスの名前、そしてその他の上位レベルの接続情報を定義します。

索引ノード (inode)

Linux はファイルシステム内のすべてのオブジェクトを、inode (index node の省略形) というオブジェクトを使用して管理します。inode はファイル、ディレクトリー、または別のオブジェクトへのシンボリック・リンクを参照することができます。デバイスやメモリーなどの他のタイプのオブジェクトはファイルによって表されるため、inode はこれらのオブジェクトを表すためにも使用されることに注意してください。

ここで述べている inode は、VFS 層の inode (メモリー内 inode) のことですが、それぞれのファイルシステムにも inode が含まれます。各ファイルシステムに含まれる inode はディスク上に存在し、その特定のファイルシステムに固有のオブジェクトに関する詳細情報を提供します。

VFS の inode は、スラブ・アロケーターを使って (inode_cache から) 割り振られます (スラブ・アロケーターについての詳細は、「参考文献」のリンクを参照してください)。inode を構成するのは、inode を記述するデータと操作、inode の内容、そして inode で可能な各種の操作です。図 4 に示す単純な VFS inode は多数のリストで構成されていて、そのなかの 1 つが、この inode を参照する dentry を参照します。ここに含まれるオブジェクト・レベルのメタデータは、操作に伴い記録されるお馴染みの時刻 (作成時刻、アクセス時刻、変更時刻) ならびに所有者およびアクセスの権データ (group-id、user-id、アクセス権) で構成されています。inode が参照するこの inode で可能なファイル操作のほとんどは、システム・コール・インターフェースに直接マッピングされます (openreadwriteflush など)。さらに inode 特有の操作への参照もあります (createlookuplinkmkdir など)。そして最後に、アドレス空間オブジェクトによって表されるオブジェクトを対象とした実際のデータを管理するための構造体があります。アドレス空間オブジェクトとは、ページ・キャッシュに含まれる inode の各種ページを管理するオブジェクトのことです。アドレス空間オブジェクトは、ファイルのページを管理するためだけでなく、ファイルのセクションを個々のプロセス・アドレス空間にマッピングするためにも使用されます。アドレス空間オブジェクトには独自の操作セットがあります (writepagereadpagereleasepage など)。

図 4. VFS inode の簡易表現
VFS inode の簡易表現

以上の情報はすべて、./linux/include/linux/fs.h に記載されています。

ディレクトリー・エントリー (dentry)

ファイルシステムの階層的な性質は、dentry オブジェクトと呼ばれる VFS 内の別のオブジェクトによって管理されます。ファイルシステムには 1 つのルート dentry が設定されます (スーパーブロック内で参照される dentry)。これが唯一、親のない dentry です。その他の dentry には親があり、なかには子を持つものもあります。例えば、/home/user/name という階層を持つファイルが開かれたとすると、合計 4 つの dentry オブジェクトが作成されることになります。つまり、ルートの /、ルート・ディレクトリーの home エントリー、home ディレクトリーの user エントリー、そして user ディレクトリーの name エントリーのそれぞれに対して 1 つのオブジェクトです。このように、dentry は今日使われている階層型ファイルシステムにすんなりとマッピングされます。

dentry オブジェクトは dentry 構造体によって (./linux/include/fs/dcache.h 内に) 定義されます。このオブジェクトは、ファイルシステム内でのエントリーと他のエントリーとの関係を追跡したり、物理データ (ファイル名など) を追跡したりする多数の要素からなります。図 5 は、dentry オブジェクトの概略図です。このオブジェクトが含まれる特定のファイルシステム・インスタンスは、dentry が参照する super_block によって定義されます。図 5super_block の次にあるのはオブジェクトの親の dentry (親ディレクトリー) で、その後にリスト内に含まれる子 dentry が続きます (オブジェクトがディレクトリーである場合)。続いて定義されているのは dentry の操作です (hashcomparedeleterelease などの操作があります)。操作の次に定義されているオブジェクトの名前は inode の中に保持されるのではなく、この dentry に保持されます。そして最後に、VFS inode への参照が定義されます。

図 5. dentry オブジェクトの簡易表現
dentry オブジェクトの簡易表現

dentry オブジェクトが存在するのはファイルシステムのメモリー内だけで、ディスク上には保存されないことに注意してください。永続的に保存されるのはファイルシステムの inode のみで、dentry オブジェクトはパフォーマンス向上のために使用されます。dentry 構造体の詳細は、./linux/include/dcache.h を参照してください。

ファイル (file) オブジェクト

Linux システムで開かれているファイルごとに、file オブジェクトが存在します。このオブジェクトに含まれるのは、特定ユーザーのオープン・インスタンスに固有の情報です。図 6 は、極めて簡略化した file オブジェクトの図です。この図に示されているように、path 構造体は dentryvfsmount 両方への参照が定義されます。file オブジェクトのそれぞれに定義される一連のファイル操作は、お馴染みのものです (openclosereadwriteflush など)。フラグとアクセス権も定義されます (グループおよび所有者を含む)。そして最後に、特定のファイル・インスタンスに対してステートフルなデータ (ファイルへの現行オフセットなど) が定義されます。

図 6. file オブジェクトの簡易表現
file オブジェクトの簡易表現

オブジェクト間の関係

VFS 層の重要な各種オブジェクトについて概説したところで、これらのオブジェクトをまとめて 1 つの図に示し、それぞれがどのように関連しているのかを見てみましょう。この記事ではこれまでボトムアップ方式でオブジェクトを調べてきたので、今度はユーザーの観点で逆の方向から見ることにします (図 7 を参照)。

最上位にあるのは、プロセスのファイル記述子リストが参照するオープン file オブジェクトです。file オブジェクトが参照する dentry オブジェクトは、inode オブジェクトを参照します。inode オブジェクトと dentry オブジェクトの両方が参照するのは、そのベースとなる super_block オブジェクトです。複数の file オブジェクトが同じ dentry オブジェクトを参照する場合もあります (2 人のユーザーが同じファイルを共有している場合など)。図 7 では、dentry オブジェクトが別の dentry オブジェクトを参照している点にも注意してください。この場合、ディレクトリーがファイルを参照し、そのファイルが特定ファイルの inode オブジェクトを参照します。

図 7. VFS の主要なオブジェクト間の関係
VFS の主要なオブジェクト間の関係

VFS のアーキテクチャー

VFS の内部アーキテクチャーは、ファイルシステムを抽象化するディスパッチ層と、ファイルシステム操作のパフォーマンスを向上させるためのいくつものキャッシュからなります。このセクションでは内部アーキテクチャーについて調べるとともに、主要なオブジェクトがどのようにやりとりするのかも調べます (図 8 を参照)。

図 8. VFS 層の概要
VFS 層の概要

VFS 内で動的に管理される 2 つの主要なオブジェクトは、dentryinode です。これらのオブジェクトは、そのベースとなるファイルシステムにアクセスする際のパフォーマンスを向上させるためにキャッシュに入れられます。ファイルを開くと、パスを表すディレクトリー・レベルを示すエントリーが dentry キャッシュに取り込まれます。オブジェクトには、ファイルを表す inode も作成されます。dentry キャッシュはハッシュ・テーブルを使って作成され、オブジェクトの名前を基にハッシュ値が計算されます。dentry_cache スラブ・アロケーターから割り当てられる dentry キャッシュのエントリーは、メモリーに負担がかかると、LRU (Least Recently Used) アルゴリズムによってエントリーを削除します。dentry キャッシュに関連する関数は、./linux/fs/dcache.c (および ./linux/include/linux/dcache.h) にあります。

inode キャッシュは、検索を高速化するために 2 つのリストと 1 つのハッシュ・テーブルとして実装されます。最初のリストが現在使用中の inode を定義し、2 つ目のリストが未使用の inode を定義します。使用中の inode はハッシュ・テーブルにも保存されます。個々の inode キャッシュ・オブジェクトは、inode_cache スラブ・アロケーターから割り当てられます。inode キャッシュに関連する関数は、./linux/fs/inode.c (および ./linux/include/fs.h) にあります。現在の実装では、dentry キャッシュが inode キャッシュのマスターとなるため、dentry オブジェクトが存在するときには、inode オブジェクトも inode キャッシュに存在することになります。検索は dentry キャッシュで行われ、その結果 inode キャッシュ内のオブジェクトが検出されます。


さらに詳しく調べてください

この記事では、VFS とその手法、そしてさまざまなファイルシステムへのアクセスを統一するために使用されているオブジェクトについて表面的に説明したにすぎません。このように、サブシステムからして Linux はスケーラブルで柔軟性と拡張性に優れています。「参考文献」セクションで紹介している資料を参考に、さらに詳しく学んでください。

参考文献

学ぶために

製品や技術を入手するために

  • developerWorks から直接ダウンロードできる IBM ソフトウェアの試用版を使用して、Linux で次の開発プロジェクトを構築してください。

議論するために

  • My developerWorks コミュニティーに加わってください。自分個人のプロファイルとカスタム・ホーム・ページを作成して、自分の興味に合わせて developerWorks をカスタマイズしたり、他の developerWorks ユーザーと対話したりすることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=432972
ArticleTitle=Linux 仮想ファイルシステム・スイッチの徹底調査
publish-date=08312009