一、VFS 抽象层架构总览
虚拟文件系统(Virtual File System,VFS)是 Linux 内核为统一不同文件系统接口而设计的抽象层。无论是 ext4、XFS、Btrfs、NFS、procfs 还是 sysfs,都通过 VFS 提供统一的文件操作接口:open、read、write、close、mmap、ioctl。
VFS 的核心设计哲学是「面向对象」——用一组结构体模拟多态:
struct file_operations {
ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
int (*mmap)(struct file *, struct vm_area_struct *);
int (*open)(struct inode *, struct file *);
int (*release)(struct inode *, struct file *);
// ...
} ____cacheline_aligned;
理解 VFS 的三大核心缓存——inode 缓存、dentry 缓存(dcache)、页缓存(page cache),以及进程的文件描述符表,是掌握 Linux I/O 性能优化的关键。
二、文件描述符表:从进程到 file 结构体
每个进程的 task_struct 中嵌入了 struct files_struct:
struct files_struct {
atomic_t count;
spinlock_t file_lock ____cacheline_aligned_in_smp;
struct fdtable __rcu *fdt;
struct fdtable fdtab;
} ____cacheline_aligned;
关键设计点:
- fdtable 的两级数组:低层是
struct file **fd指针数组,默认 64 个;超出时分配更大的 fdtable 并替换(RCU 机制保护)。 - close-on-exec 位图:
struct file **close_on_exec独立维护 exec 时需要关闭的 fd 集合,避免遍历全表。 - RCU 延迟释放:旧 fdtable 用 RCU 延迟释放,确保其他 CPU 上正在使用旧引用的代码安全退出。
dup/dup2 的底层实现:不是复制 file 结构体,而是让多个 fd 指针指向同一个 struct file,引用计数加一。这也是 fork 后父子进程共享同一个文件偏移量的根本原因。
三、inode 缓存:哈希表 LRU 的双层管理
inode 缓存的目的是避免每次路径查找都去磁盘读取 inode 元数据。VFS 通过两个数据结构管理:
// 全局哈希表:通过 (sb, ino) 快速查找
static struct hlist_head *inode_hashtable;
// 全局 LRU 链表(两个:active 和 inactive)
static LIST_HEAD(inode_unused);
哈希表大小在启动时动态分配(ihash_entries 参数可控制,默认与内存成正比):
[~]$ cat /proc/slabinfo | grep inode_cache
inode_cache 88216 90210 632 25 4 : tunables ...
# 每个 inode_cache 对象约 632 字节,全部来自 slab
关键机制:
- I_REFERENCED 标记:当 inode 被访问时设置此标志,表示「热」。下次 LRU 扫描时,若仍为 referenced,会回落到 active 链表尾部;否则降级为 inactive 并可能被回收。
- writeback 控制:脏 inode 通过

发表评论 取消回复