rootfsとルートファイルシステム
Rev.3を表示中。最新版はこちら。
rootfsとルートファイルシステムとは別物です(と理解しています)。rootfsはext2/3のようなvfs下の1つのファイルシステムで、むしろprocやsysfsの特殊ファイルシステムの1つと言った方がいいかもしれません。ファイルシステムと言えば、ストレージを持つハードディスクをイメージしますが、ユーザから見た場合、vfsのファイルシステムは、メモリー上のツリー構造(dentry)で管理したオブジェクト、と解釈した方が理解しやすいかと思います。厳密には、キャッシュ/実デバイスとのインターフェースも含んでの機能ですが。そして、ルートファイルシステムが、ハードディスク上の実デバイス、(そしてこのデバイスは、ext2であったりext3であったりとするわけです。)と理解した方が、rootfsとルートファイルシステムの関係が見えてきます。
rootfsは、static struct file_system_type rootfs_fs_typeで定義され、システム初期化時にinit_rootfs(void)をコールする事で、register_filesystem関数でシステムのファイルシステムとして登録されます。このrootfsはスーパブロックを操作するコールバックしか定義されていません。ユーザがこのファイルシステムを操作できない。と言う事もあるかと思いますが、このファイルシステムへの読み書きが発生する場合(直接rootfsをルートファイルシステムとするようなケース)、ramfsのコールバック関数が呼ばれる事になるからです。rootfsの実態はramfsとも言える訳です。
実際、rootfsの定義は、static struct file_system_type rootfs_fs_typeだけで、inode等の他のコールバック関数は定義されていません。
get_sbであるrootfs_get_sbコールバックを見てみると、スーパブロックの取得はramfs_fill_superをコールしています。そして、sb->s_opにramfsのそれを、inode取得にramfsのそれをコールする事で実現しています。
そして、d_alloc_root()で、そのinodeに対するdentryを、/ として取得します。ある意味これ故、rootfsと言うところでしょうか。
static struct file_system_type rootfs_fs_type = { .name = "rootfs", .get_sb = rootfs_get_sb, .kill_sb = kill_litter_super, }; static int rootfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super, mnt); } static int ramfs_fill_super(struct super_block * sb, void * data, int silent) { struct inode * inode; struct dentry * root; sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = RAMFS_MAGIC; sb->s_op = &ramfs_ops; sb->s_time_gran = 1; inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0); if (!inode) return -ENOMEM; root = d_alloc_root(inode); if (!root) { iput(inode); return -ENOMEM; } sb->s_root = root; return 0; } struct dentry * d_alloc_root(struct inode * root_inode) { struct dentry *res = NULL; if (root_inode) { static const struct qstr name = { .name = "/", .len = 1 }; res = d_alloc(NULL, &name); if (res) { res->d_sb = root_inode->i_sb; res->d_parent = res; d_instantiate(res, root_inode); } } return res; }rootfsとはそれだけのものです。そしてルートファイルシステム(カーネルとかライブラリー等のイメージが書き込まれた実デバイス)を、rootfsの/にマウントすることで、システムが起動するわけです。
補足
ルートファイルシステムのマウントは、rootfs下に/rootを作成し、そこにルートファイルシステムをマウントした後、マウントマウントポジションを/rootが/となるように再マウントすることで実現しています。また、rootfsはramfs上に作成される。と説明があったりいたしますが、上で見てきたように、この説明は正しくありません。rootfsとramfsはファイルシステムです。正しくはrootfsはramfsは別のものであり、ただrootfsのファイルオペレーションのコールバック関数はramfsのそれを使っている。という事実であり、rootfsの実装はramfsのそれである。と言うのが正しいところでしょうか。