この記事についてClaude(Anthropic)との共同編集により作成されました。
要約
- mountの実体は、カーネル内のVFSがパス解決時に「別のファイルシステムにジャンプする」仕組み
- vfsmount構造体がマウントポイントと新しいファイルシステムのルートを紐付けるのが核心
- bind mount・NFS・FUSEも、VFSが差異を吸収して「ローカルフォルダに見せる」点は同じ
mountって何が起きてるの?
mount /dev/sdb1 /mnt/dataこのコマンドを打つと、/mnt/data/ に /dev/sdb1 の中身が見えるようになる。ローカルのフォルダと同じように ls も cat も使える。リモートのNFSやS3でも同じ話だ。
「別のデバイスやネットワーク越しのストレージが、ローカルフォルダと同じように扱える」というのがmountの利点だとはわかっている。でも、それをどうやって実現してるの? というところはあまり説明されない。
結論から言うと、仕組みはシンプルだ。Linuxカーネル内のVFS(仮想ファイルシステム)という層が、パスを解決するときにこっそり「別のファイルシステムにジャンプ」している。それだけ。
この記事ではその仕組みを順を追って説明する。
VFS(Virtual File System)がすべての鍵
LinuxカーネルにはVFS(Virtual File System)という抽象化レイヤーがある。
アプリ (open/read/write) ↓ VFS レイヤー(カーネル内) ↓実際のファイルシステムドライバ(ext4 / NFS / FUSE / ...) ↓デバイス・ネットワーク・ユーザー空間プロセスopen() や read() といったシステムコールはVFSが受け取る。VFSは「このパスはどのファイルシステムに属するか」を判断して、適切なドライバに処理を投げる。
要するにVFSは翻訳係だ。アプリ側はext4だろうとNFSだろうとFUSEだろうと、同じ open()/read()/write() を呼ぶだけでいい。差異を吸収するのがVFSの仕事^1。
VFSを支える4つのデータ構造
VFSは内部でいくつかの構造体を使ってファイルシステムを管理している。マウントを理解するうえで重要なのがこの4つ。
| 構造体 | 役割 |
|---|---|
superblock | マウントされたファイルシステム全体のメタデータ。「ここからこのFSが始まります」という名刺みたいなもの |
inode | ファイル・ディレクトリ1つを表す。パーミッション・サイズ・データの場所などを持つ |
dentry | パスの1要素を表す。/usr/bin/ls なら usr, bin, ls それぞれが1つの dentry |
vfsmount | 「このマウントポイントには、このFSのルートがある」という対応を保持する構造体 |
dentry がパスのパーツ一つ一つだとすると、vfsmount は「ここで別のFSに切り替わりますよ」という標識のようなものだ。このvfsmountがmountの実体になる。
マウントの内部動作:4ステップで理解する
mount /dev/sdb1 /mnt/dataこのコマンドを打ったとき、カーネルの中では何が起きているか。
ステップ1:mountコマンド → システムコール
mountコマンドは内部で mount(2) システムコールを呼ぶ。カーネルに「このデバイスをこのパスに接続してくれ」と伝えるだけ^2。
ステップ2:カーネルがファイルシステムを読み込む
カーネルは /dev/sdb1 の先頭ブロックを読み込んで「あ、これはext4だな」と判別し、対応するドライバを呼び出す。ドライバは superblock 構造体を初期化して、ファイルシステム全体のメタデータをカーネルに渡す。
ステップ3:vfsmountの生成と接続
カーネルは新しい vfsmount 構造体を生成し、次の3つを記録する:
- mnt_sb:この vfsmount が指す superblock(=
/dev/sdb1のFS) - mnt_root:そのFSのルートディレクトリの dentry
- mnt_mountpoint:接続先マウントポイントの dentry(=
/mnt/dataの dentry)
これがmount操作の実体。 /mnt/data という dentry に、新しいFSのルートが紐付けられた。
ステップ4:パス解決時の「ジャンプ」
ユーザーが /mnt/data/hello.txt を開こうとすると、VFSはパスを左から1要素ずつ dentry をたどって解決していく。
/mnt/data の dentry に差し掛かったとき、VFSはそこに vfsmount が接続されていることを検知する。そのまま既存のツリーをたどるのではなく、vfsmountが指すFSのルートにジャンプする。
/mnt/data ← ここでマウントポイントを検知 ↓ ジャンプ! /dev/sdb1 のルート └── hello.txt ← ここからドライバが inode を返すこのジャンプ処理が「別のFSがローカルフォルダに見える」仕組みの核心中の核心。アプリ側は全く関知しない。
種類別:どうやって「ローカルフォルダ」に見せるか
VFSのジャンプ機構は共通だが、ドライバがその先で何をするかは種類によって異なる。
① ローカルデバイスマウント(ext4 / xfsなど)
最もシンプルなケース。ドライバがブロックデバイスを直接読み書きする。上で説明したVFSのジャンプだけで完結する。
② bindマウント
mount --bind /実際のパス /見せたいパス新しいデバイスを持ち込むのではなく、既存のディレクトリツリーの別の場所を再マウントする。vfsmountが別の dentry を指すように設定されるだけで、データの実体は1つのまま。
シンボリックリンクより強力で、chroot環境やコンテナの構築に使われる。Dockerがコンテナにホストのディレクトリを見せるときにもこの仕組みが使われている。
③ NFS(ネットワークファイルシステム)
mount -t nfs server:/share /mnt/nfsNFSドライバがリモートサーバーとの通信レイヤーを抽象化する。VFSからはドライバに処理を渡しただけだが、ドライバ内部でネットワーク越しにRPCを投げてデータを取得する。
open("/mnt/nfs/file") → VFS → NFSドライバ → ネットワーク RPC → サーバー ← データ返却 ← アプリにファイルディスクリプタを返すアプリはNFSを意識しない。VFSが差異を隠蔽している^3。
④ FUSE(Filesystem in Userspace)
前提として、Linuxのプロセス実行環境はカーネル空間とユーザー空間に分かれている。
- カーネル空間:OSの本体が動く特権領域。デバイスやメモリに直接触れる。バグるとシステムごと落ちる
- ユーザー空間:普通のプログラムが動く場所。カーネルには
open()などのシステムコール経由でしか触れない。バグってもそのプロセスが死ぬだけ
通常のファイルシステムドライバ(ext4など)はカーネル空間に実装される。FUSEは少し変わった仕組みで、カーネルのファイルシステムドライバをユーザー空間のプログラムとして実装できる。S3やGoogle Driveをマウントするツール(rclone, s3fsなど)がこれを使っている^4。
open("/mnt/s3/file") → VFS → FUSEカーネルモジュール → /dev/fuse 経由でユーザー空間プロセスにリクエスト転送 ← ユーザー空間プロセスが処理してレスポンス返却 ← アプリにファイルディスクリプタを返すFUSEは /dev/fuse という特殊デバイスを介してカーネルとユーザー空間プロセスを接続する。ユーザー空間のプログラムが read や write 等の操作ごとにコールバックを実装する形で、クラウドAPIやデータベースなど任意のバックエンドに対応できる^5。
まとめ
| 技術 | 「ローカルに見せる」仕組み |
|---|---|
| ローカルデバイス | vfsmount + dentryのジャンプのみ |
| bindマウント | 別のdentryを再マウント |
| NFS | ドライバ内でネットワーク通信に変換 |
| FUSE | ドライバがユーザー空間プロセスへ転送 |
どのケースも、VFSが open() などのシステムコールを受け取り、パスを解決しながら適切なドライバに処理を委譲する構造は変わらない。
mountの正体は「VFSがパス解決時にジャンプするだけ」。シンプルだけど強力な仕組みだ。次にmountコマンドを打つとき、裏で vfsmount が生えてジャンプが起きているのを想像すると、少し楽しくなるはず。
参考文献
- Linux Kernel Documentation: Virtual File System https://docs.kernel.org/filesystems/vfs.html
- Linux Kernel Documentation: Filesystem Mount API https://docs.kernel.org/filesystems/mount_api.html
- Linux Kernel Documentation: FUSE https://www.kernel.org/doc/html/next/filesystems/fuse.html
- Wikipedia: Filesystem in Userspace https://en.wikipedia.org/wiki/Filesystem_in_Userspace
- JuiceFS Blog: FUSEのカーネル・ユーザー空間設計解説 https://juicefs.com/en/blog/engineering/design-fuse-kernel-user-space