連載
» 2010年09月01日 00時00分 公開

仮想ファイルシステムのありがたみを知ろう = ファイルシステム種別とスーパーブロックについて =作りながら理解するファイルシステムの仕組み(7)(2/3 ページ)

[森 崇 株式会社 永和システムマネジメント,@IT MONOist]

ファイルシステム種別

 前述のとおり、Linuxではさまざまな種類のファイルシステムを扱うことができます。このため、ファイルシステム種別ごとの管理データが必要となります。この管理データが「file_system_type」という構造体であり、「file_systems」というグローバル変数(ポインタ変数)から単方向リストでつながっています(図3)。


ファイルシステム種別のデータ管理 図3 ファイルシステム種別のデータ管理

 このfile_system_typeは、ファイルシステムをインストールしたときに登録され、アンインストールするときに削除されます。その登録・削除関数は以下のとおりです(表1)。

ファイルシステム登録・削除関数 説明
int register_filesystem(struct file_system_type * fs) ファイルシステム種別(fs)を登録する
int unregister_filesystem(struct file_system_type * fs) ファイルシステム種別(fs)を削除する
表1 ファイルシステム登録・削除関数について

 file_system_typeは、ファイルシステムがマウントされていない状態でも、カーネルのメモリ上に常駐しており、ローカルファイルシステムのデータの中で1番ライフサイクルが長いものです。ファイルシステムをマウントする前にも存在していますし、ファイルシステムをアンマウントした後も存在しています(図4)。つまり、このデータには、ファイルシステム固有のマウント・アンマウント処理の共通インターフェイスがあるということです。それらの関数は以下のとおりです(表2)。

file_system_typeのライフサイクル 図4 file_system_typeのライフサイクル
ファイルシステム固有のマウント・アンマウント関数 説明
int (*get_sb) (struct file_system_type *, int, const char *, void *, struct vfsmount *) ファイルシステム固有のマウント処理を実行する。主に、スーパーブロックの読み込みやルートディレクトリの読み込みを行う
void (*kill_sb) (struct super_block *) ファイルシステム固有のアンマウント処理を実行する。主に、ファイルシステム固有のデータのメモリ解放などを行う
表2 ファイルシステム固有のマウント・アンマウント関数について

 それでは、Androidエミュレータをデバッグして、file_systemsのリスト管理状況を見てみましょう(図5)。

ファイルシステム種別管理 図5 ファイルシステム種別管理

 file_systemsに複数のファイルシステムが登録されていることが分かります。まず先頭には「sysfs」、次に「rootfs」とつながっていますね。sysfsとrootfsとでは、ファイルシステムが異なるため、get_sb()、kill_sb()に登録されている関数も違うことが分かります。つまり、VFS層としては、これらの関数インターフェイスを定義しておき、そこに登録されている関数を呼び出すだけで、それぞれ異なる処理(sysfs_get_sb()、rootfs_get_sb()など)が実行されるというわけです。これこそが、異なるファイルシステムを統一した方法でアクセスできる仕組みなのです! 今後、VFS層のさまざまなデータを見ていきますが、基本的にはこのような構造ですので、ぜひ覚えておきましょう。

 最後に、「fs_supers」というメンバがありますが、これはマウント処理で作成される「super_block」(後述)をマウントポイントごとに関連付けるためのものです。つまり、fs_supersをたどっていけば、マウントされているすべてのスーパーブロック情報を参照できるということです。

スーパーブロック

 連載第2回「素晴らしきファイルシステムのデータ管理」で、ファイルシステムのデータの中で最も重要となるものがスーパーブロックであると説明しました。これに対応するVFS層のデータがsuper_blockです。super_blockは、さまざまなファイルシステムのスーパーブロックのデータを扱えるように、スーパーブロックに対する操作やデータを抽象化した構造になっています。ファイルシステム固有のスーパーブロックのデータについては、super_blockのメンバである「s_fs_info」に登録します。このメンバの型はファイルシステム固有の型ではなく、抽象化された型(void*)です。操作については、同様にsuper_blockの「s_op」に登録します。s_opの型は、「super_operations」であり、以下に示す関数ポインタテーブルになっています(数が多いのでtarfsで主要なものだけピックアップしています)(表3)。

super_operationsの関数 説明
void (*clear_inode) (struct inode *) ファイルシステム固有のinodeメモリの解放を行う
void (*put_super) (struct super_block *) ファイルシステム固有のスーパーブロックのメモリ(s_fs_infoなど)解放を行う。アンマウント処理の延長で呼び出される
int (*statfs) (struct dentry *, struct kstatfs *) ファイルシステム情報を取得する
表3 主なsuper_operationsの関数について

 super_blockは、ファイルシステムをマウントすると必ずメモリ獲得され、アンマウントするとメモリ解放されます。また、Linuxではマウントポイントを複数持つことができますが、マウントポイントごとにsuper_blockが割り当てられます。このため、Linuxカーネルは複数のsuper_blockを管理しておく必要があります。「super_blocks」というグローバル変数は、これらのsuper_blockを双方向リストへ管理するヘッダであり、図6のような構造になっています。

super_blockのリスト管理 図6 super_blockのリスト管理

 また、同じファイルシステムのsuper_block同士は、前述したとおりfile_system_typeから双方向リストでつながっています。図7では、「yaffs2」が2つのデバイス(mtdblock0、mtdblock1)をマウントしている状態を表しています。

同じファイルシステム同士のsuper_blockのリスト構造 図7 同じファイルシステム同士のsuper_blockのリスト構造

Copyright © ITmedia, Inc. All Rights Reserved.