本页目录
临时与伪文件系统
覆盖: 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 handler
// 例子: /proc/<pid>/status
static const struct file_operations proc_status_operations = ;
// seq_file 接口 (fs/seq_file.c):
// 简化内核生成文本输出的通用框架
// 自动处理缓冲、分页、seek
// .start() / .next() / .stop() / .show()
// 实现: task_state() → seq_printf() 输出每个字段
// 进程看到的是一个纯文本文件,但内容是实时生成的
关键 proc 文件
// /proc/<pid>/maps: VMA 列表 (遍历 mm->mmap)
// /proc/<pid>/smaps: 每 VMA 的详细内存统计
// /proc/<pid>/fd/: 每个 fd 的符号链接 → file path
// /proc/<pid>/attr/: 安全属性 (SELinux/AppArmor)
// /proc/<pid>/mem: 进程内存读写 (ptrace 替代)
sysfs: 设备模型
// fs/sysfs/
// sysfs 基于 kernfs 框架 (6.x+ 重构)
// 每个 kobject → 一个 sysfs 目录/文件
// kernfs_node 是 sysfs 的核心:
;
// 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 *;
// 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
// 数据存储在 page cache 中 (匿名页 + swap-backed)
// 没有磁盘后备 → 断电数据丢失
// 支持 swap: 内存紧张时写 swap
// 使用场景:
// /tmp: 临时文件
// /dev/shm: POSIX 共享内存
// /run: daemon 的 PID 文件和 socket
// /var/run: 向后兼容的符号链接 → /run
// 特性:
// 自动增长 (上限: size mount option, 或 50% RAM)
// 支持 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 backing → 数据永远在内存
// 没有大小限制 → 可能耗尽内存 (危险!)
// 没有 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 胶水层
// → 重复代码, 各自有 bug
// kernfs 统一了 VFS 交互 → 减少重复, 提高可靠性
实现伪文件系统的方式
方案 1: seq_file (用于 proc 中的文本输出)
→ 适合: /proc/<pid>/status 等一行一行生成的文本
方案 2: kernfs (用于 sysfs/cgroupfs)
→ 适合: 属性文件 (.show/.store), 树状结构
方案 3: debugfs (用于调试)
→ 适合: 简单的 file_operations 注册
方案 4: libfs (简单文件系统)
→ 适合: 只有几个文件的伪文件系统
→ fs/libfs.c: simple_fill_super(), simple_lookup_dir(), ...
→ 极少量胶水代码
调试
# proc 文件系统统计
|
# sysfs 设备树
# tmpfs 使用量
# 内核中 debugfs 的使用 (需 root)
参考与延伸
- 内核文档:
Documentation/filesystems/proc.rst,Documentation/filesystems/sysfs.rst,Documentation/filesystems/tmpfs.rst,Documentation/filesystems/debugfs.rst - 源码:
fs/proc/— procfsfs/sysfs/— sysfsfs/kernfs/— kernfs 框架fs/debugfs/— debugfsmm/shmem.c— tmpfsdrivers/base/devtmpfs.c— devtmpfsfs/libfs.c— 简单文件系统工具
关键词: procfs, sysfs, debugfs, tracefs, tmpfs, devtmpfs, kernfs, seq_file, 伪文件系统