3 分で読了 #linux-kernel #file-system
このページの目次

一時ファイルシステムと擬似ファイルシステム

カバー範囲: procfs/sysfs/debugfs/tracefs → tmpfs (shmem) → devtmpfs → ramfs → kernfs フレームワーク → ファイルシステム実装方法 (擬似 vs 実在) カーネルバージョン: 2.6 ~ 6.x

概要

「擬似ファイルシステム」はデータをディスクに保存しません。データはカーネルによってアクセス時に動的に生成されます。最も一般的な例は、/proc(プロセス情報)、/sys(デバイスモデル)、/sys/kernel/debug(デバッグインターフェース)です。これらは通常のファイルのように見えますが、read() システムコールはディスク I/O ではなく、カーネル内のコールバック関数をトリガーします。

擬似ファイルシステムの核心的な価値は、統一された、ツールフレンドリーなインターフェースを提供することです。cat /proc/meminfo は、システムコール、ioctl、または特殊デバイスよりも直感的です。


procfs: プロセス情報

// fs/proc/
// 各プロセスの /proc/<pid>/ ディレクトリ:
//   task_struct → proc_dir_entry → inode → dentry
//   ファイルへのアクセス → proc 固有の read ハンドラをトリガー

// 例: /proc/<pid>/status
static const struct file_operations proc_status_operations = {
    .open       = proc_single_open,
    .read       = seq_read,       // seq_file インターフェースを使用
    .release    = proc_single_release,
};

// seq_file インターフェース (fs/seq_file.c):
//   カーネルがテキスト出力を生成するための汎用フレームワークを簡素化
//   バッファリング、ページング、シークを自動処理
//   .start() / .next() / .stop() / .show()

// 実装: task_state() → seq_printf() で各フィールドを出力
//   プロセスからは純粋なテキストファイルとして見えるが、内容はリアルタイムで生成される

主要な proc ファイル

// /proc/<pid>/maps: VMA リスト (mm->mmap をトラバース)
// /proc/<pid>/smaps: 各 VMA ごとの詳細なメモリ統計
// /proc/<pid>/fd/: 各 fd のシンボリックリンク → ファイルパス
// /proc/<pid>/attr/: セキュリティ属性 (SELinux/AppArmor)
// /proc/<pid>/mem: プロセスメモリへの読み書き (ptrace の代替)

sysfs: デバイスモデル

// fs/sysfs/
// sysfs は kernfs フレームワークベース (6.x+ でリファクタリング)
// 各 kobject → sysfs のディレクトリ/ファイル 1つ

// kernfs_node が sysfs の中核:
struct kernfs_node {
    const char          *name;
    struct kernfs_node  *parent;
    const struct kernfs_ops *ops;       // ファイル操作
    struct kernfs_elem_dir dir;         // 子ノード (ディレクトリの場合)
    struct kernfs_elem_symlink symlink; // シンボリックリンク
    struct kernfs_elem_attr attr;       // 属性ファイル
};

// sysfs 属性ファイル:
//   .show(): cat /sys/... → テキストを生成
//   .store(): echo xxx > /sys/... → パースして適用

// デバイスモデルのツリー構造:
//   /sys/devices/          ← 実デバイスツリー
//   /sys/bus/              ← バスタイプ → devices/ へのリンク
//   /sys/class/            ← 機能別分類 → devices/ へのリンク
//   /sys/block/            ← ブロックデバイス

debugfs / tracefs

// fs/debugfs/
// 非安定な API: 開発者向けのデバッグインターフェース
// 本番システムでは依存しないこと (内容/パスはバージョン間で変化する可能性がある)

struct dentry *debugfs_create_file(const char *name, umode_t mode,
                                     struct dentry *parent, void *data,
                                     const struct file_operations *fops);

// tracefs (fs/tracefs/):
//   ftrace / tracepoints のマウントポイント
//   /sys/kernel/tracing/ ← tracefs をマウント
//   旧来の /sys/kernel/debug/tracing (debugfs) の代替

tmpfs: メモリファイルシステム

// mm/shmem.c
// tmpfs = shmem ファイルシステム
// マウント: mount -t tmpfs tmpfs /tmp

// データはページキャッシュに保存される (匿名ページ + swap 対応)
//   ディスクバックエンドなし → 電源断でデータ消失
//   swap サポート: メモリ不足時にスワップへ書き出し

// 使用例:
//   /tmp:       一時ファイル
//   /dev/shm:   POSIX 共有メモリ
//   /run:       デーモンの PID ファイルとソケット
//   /var/run:   後方互換性のためのシンボリックリンク → /run

// 特徴:
//   自動拡張 (上限: size マウントオプション、または RAM の 50%)
//   POSIX ACL、xattr、O_TMPFILE をサポート

devtmpfs

// drivers/base/devtmpfs.c
// /dev における動的デバイスノード管理
// カーネル起動時: devtmpfs をマウント → 既知のデバイス (例: /dev/sda, /dev/tty) を埋める
// デバイスホットプラグ: udev が uevent を受信 → デバイスノードの作成/削除

// devtmpfs は、早期起動段階 (udev がまだ実行されていない間) でさえも
//   基本的なデバイスノードが利用可能であることを保証する
//   2.6.32 以降のカーネルで自動処理

ramfs

// fs/ramfs/
// 極めてシンプルなメモリファイルシステム
//   swap バッキングなし → データは常にメモリ上に存在
//   サイズ制限なし → メモリ枯渇のリスクあり (危険!)
//   inode 操作の複雑さなし → コードが最短

// ソースコードは約 200 行 (inode.c + file-mmu.c) のみ
// 主に特定用途 (initramfs 内部、rootfs) で使用

kernfs フレームワーク (6.x+)

// fs/kernfs/
// sysfs、cgroupfs の共有基盤
// 提供機能:
//   1. 階層的名前空間 (ディレクトリツリー)
//   2. ファイル操作 (read/write/mmap/poll)
//   3. シンボリックリンクとハードリンク
//   4. RCU 安全なトラバース

// なぜ kernfs が必要なのか?
//   旧来の sysfs と cgroupfs は独立して VFS グルーイングレイヤーを実装していた
//   → コードの重複、個別のバグ
//   kernfs が VFS 相互作用を統一 → 重複を削減し、信頼性を向上

擬似ファイルシステムの実装方法

案 1: seq_file (proc 内のテキスト出力用)
  → 適している: /proc/<pid>/status など、行単位で生成されるテキスト

案 2: kernfs (sysfs/cgroupfs 用)
  → 適している: 属性ファイル (.show/.store)、ツリー構造

案 3: debugfs (デバッグ用)
  → 適している: simple な file_operations の登録

案 4: libfs (簡易ファイルシステム)
  → 適している: ファイル数が少ない擬似ファイルシステム
  → fs/libfs.c: simple_fill_super(), simple_lookup_dir(), ...
  → 極めて少ないグルーイングコード

デバッグ

# proc ファイルシステムの統計
cat /proc/filesystems | grep nodev  # すべての擬似ファイルシステム

# sysfs デバイスツリー
tree /sys/devices/

# tmpfs の使用量
df -t tmpfs

# カーネル内での debugfs の使用 (root が必要)
mount -t debugfs none /sys/kernel/debug

参考と拡張

  • カーネルドキュメント⁠: Documentation/filesystems/proc.rst, Documentation/filesystems/sysfs.rst, Documentation/filesystems/tmpfs.rst, Documentation/filesystems/debugfs.rst
  • ソースコード⁠:
    • fs/proc/ — procfs
    • fs/sysfs/ — sysfs
    • fs/kernfs/ — kernfs フレームワーク
    • fs/debugfs/ — debugfs
    • mm/shmem.c — tmpfs
    • drivers/base/devtmpfs.c — devtmpfs
    • fs/libfs.c — 簡易ファイルシステムツール

キーワード: procfs, sysfs, debugfs, tracefs, tmpfs, devtmpfs, kernfs, seq_file, 擬似ファイルシステム