一、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 通过
点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论