GNU/Linux で df の挙動を見てみよう。引数に(デバイスファイルではなく、普通の)ファイル名を渡すと、それが保存してあるファイルシステムを探してきて、デバイスファイルやマウントポイントなどそのファイルシステムの情報を表示する。
$ df Makefile Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda1 477514616 106381680 346803108 24% /
実はこの挙動「ファイルが保存されてあるファイルシステムを返す」をするシステムコールは無い。 df はマウントしているファイルシステムの一覧がある /etc/mtab から探しているのである。
/etc/mtab は次のようなファイルだ
sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 ... /dev/sdb2 / ext4 rw,relatime 0 0 /dev/sda1 /home/ ext4 rw,relatime 0 0 ...
マウントしているファイルシステムが一行ごとに書いてある。一行には左からスペース区切りで、ファイルシステムの名前(デバイスファイル)、マウントしてあるディレクトリ(マウントポイント)、あとは細かい情報(いまからの説明に関係がないので端折る)が書いてある。 ちなみに文法は /etc/fstab と同じである。
それでは df がどのようにファイルシステムを探しているのか見てみよう。
GNU のコードを読むのは大変なので、 busybox のコードを読んでみよう。まさにファイルがどのファイルシステムにあるのか調べる関数 find_mount_point
という関数がある。これはファイル名を渡すと、それがあるファイルシステムの情報を構造体 のポインタ struct mntent*
を返す。この構造体は /etc/mtab の一行をパースしただけである。
アルゴリズムを端折って説明すると、ファイルの stat から得られるデバイス ID (st_dev
) と一致するマウントポイントのディレクトリを /etc/mtab から一行一行読んで探し、そこからファイルシステムを特定している。
なんて泥臭いんだ! 「ファイルが保存されてあるファイルシステムを探す」ためのシステムコールがあると思っていた僕は面食らってしまった。タイトルどおり簡単ではなかった。まあ難しくもないが。