Linux 支援數十種文件系統,透過 **虛擬文件系統 (VFS, Virtual File System Switch)** 統一抽象,實現「上層統一接口,下層多樣實現」。本文深入剖析 VFS 架構、核心數據結構、緩存機制、掛載流程與文件系統註冊,助你理解內核如何管理存儲資源。
用戶空間
├── 應用程序 (read, write, open, stat...)
├── glibc (系統調用封裝)
內核空間
├── 系統調用入口 (sys_read, sys_write...)
├── VFS 虛擬文件系統 (核心抽象層)
│ ├── 文件系統類型註冊表
│ ├── 超級塊緩存
│ ├── inode 緩存
│ ├── 目錄項緩存
│ └── 文件對象緩存
├── 具體文件系統驅動
│ ├── ext4, xfs, btrfs, f2fs (磁碟)
│ ├── nfs, cifs, fuse (網路/用戶態)
│ ├── procfs, sysfs, debugfs (虛擬/內存)
│ └── tmpfs, ramfs (純內存)
├── 緩衝區緩存 / 頁面緩存
└── 塊設備驅動
struct super_block {
struct list_head s_list; // 全局超級塊鏈表
dev_t s_dev; // 設備號
unsigned long s_blocksize; // 塊大小
unsigned char s_blocksize_bits;
struct super_operations *s_op; // 操作函數表
struct export_operations *s_export_op;
struct xattr_handler **s_xattr;
struct list_head s_inodes; // 所有 inode 鏈表
struct hlist_bl_head s_anon; // 匿名 inode
struct mutex s_umount; // 掛載/卸載鎖
int s_count; // 引用計數
int s_active; // 活躍引用
void *s_fs_info; // 文件系統私有數據
struct dentry *s_root; // 根目錄 dentry
struct rw_semaphore s_umount; // ...
};
**關鍵操作函數表** `super_operations`:`alloc_inode`、`destroy_inode`、`dirty_inode`、`write_inode`、`drop_inode`、`evict_inode`、`put_super`、`sync_fs`、`freeze_fs`、`unfreeze_fs`、`statfs`、`remount_fs`...
struct inode {
umode_t i_mode; // 文件類型+權限
uid_t i_uid;
gid_t i_gid;
loff_t i_size; // 文件大小 (位元組)
struct timespec i_atime, i_mtime, i_ctime;
unsigned int i_blkbits; // 塊大小位數
unsigned long i_blocks; // 佔用塊數
struct inode_operations *i_op; // inode 操作
struct file_operations *i_fop; // 默認文件操作
struct super_block *i_sb; // 所屬超級塊
struct address_space *i_mapping; // 頁面緩存映射
struct list_head i_wb_list; // 回寫列表
union {
struct pipe_inode_info *i_pipe;
struct block_device *i_bdev;
struct cdev *i_cdev;
};
spinlock_t i_lock;
unsigned int i_flags;
unsigned long i_state; // I_NEW, I_FREEING, I_CLEAR, I_SYNC, I_DIRTY...
unsigned long dirtied_when;
unsigned long dirtied_time_when;
struct hlist_node i_hash; // inode 雜湊表
struct list_head i_lru; // LRU 回收鏈表
struct list_head i_sb_list; // 超級塊 inode 鏈表
struct list_head i_dentry; // 關聯 dentry 列表
spinlock_t i_dentry_lock;
atomic_t i_count; // 引用計數
atomic_t i_dio_count;
atomic_t i_writecount;
void *i_private; // fs 私有
};
**inode_operations** 關鍵函數:`lookup`、`create`、`link`、`unlink`、`symlink`、`mkdir`、`rmdir`、`mknod`、`rename`、`setattr`、`getattr`、`listxattr`...
struct dentry {
unsigned int d_flags; // DCACHE_*
struct dentry *d_parent; // 父目錄 dentry
struct qstr d_name; // 目錄項名稱
struct inode *d_inode; // 關聯 inode (NULL=負目錄項)
struct hlist_bl_node d_hash; // 雜湊表節點
struct list_head d_lru; // LRU 列表
struct list_head d_child; // 子目錄項鏈表
struct list_head d_subdirs; // 子目錄列表
struct list_head d_alias; // 別名 inode 鏈表
struct dentry_operations *d_op; // 目錄項操作
struct super_block *d_sb; // 所屬超級塊
void *d_fsdata; // fs 私有
};
**dentry 狀態**:正向 (d_inode != NULL)、負向 (d_inode == NULL,加速「文件不存在」查詢)、未連接 (d_parent == d_self)。
struct file {
struct path f_path; // dentry + vfsmount
struct inode *f_inode; // 便捷指針
const struct file_operations *f_op; // 文件操作函數表
atomic_long_t f_count; // 引用計數
unsigned int f_flags; // O_RDONLY, O_NONBLOCK, O_APPEND...
fmode_t f_mode; // FMODE_READ/WRITE/LSEEK...
loff_t f_pos; // 文件讀寫偏移量
struct fown_struct f_owner; // 信號驅動 I/O 擁有者
struct file_ra_state f_ra; // 預讀狀態
void *private_data; // 驅動私有數據
struct list_head f_ep_links; // epoll 關聯
spinlock_t f_lock;
};
**file_operations** 關鍵函數:`open`、`read`/`read_iter`、`write`/`write_iter`、`llseek`、`mmap`、`fsync`、`ioctl`/`unlocked_ioctl`、`poll`、`release`、`flock`、`fallocate`...
mount -t ext4 /dev/sda1 /mnt/data
1. 系統調用 mount() → sys_mount()
2. 解析設備路徑 /dev/sda1 → 獲取 block_device
3. 文件系統類型 "ext4" → 查找 file_system_type 註冊表
4. fs_type->mount() → ext4_mount()
a. 讀取超級塊 (bread)
b. 驗證魔數、特徵標誌
c. 分配 struct super_block,填充 s_op、s_root
d. 讀取根目錄 inode → 分配 dentry ("/") → 關聯
5. 將 super_block 掛入全局列表,建立 vfsmount 結構
6. 將 vfsmount 掛入命名空間 mount 树 (namespace->mnt_root)
7. 返回用戶空間
// 文件系統驅動入口
static struct file_system_type ext4_fs_type = {
.owner = THIS_MODULE,
.name = "ext4",
.mount = ext4_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
MODULE_ALIAS_FS("ext4");
MODULE_ALIAS("ext4");
// 模塊初始化
static int __init ext4_init_fs(void) {
return register_filesystem(&ext4_fs_type);
}
static void __exit ext4_exit_fs(void) {
unregister_filesystem(&ext4_fs_type);
}
掛載時內核自動 `request_module("fs-ext4")` 加載模塊。
| 類型 | 代表 | 特點 |
|---|---|---|
| 磁碟文件系統 | ext4, xfs, btrfs, f2fs | 塊設備、持久化、日志/COW |
| 網路文件系統 | nfs, cifs, cephfs | 遠程協議、頁面緩存一致性挑戰 |
| 用戶態文件系統 | fuse (fuseblk, fuse.fuse) | VFS → fuse 驅動 → 用戶態 daemon → 任意後端 |
| 虛擬/內存文件系統 | procfs, sysfs, debugfs, tmpfs, ramfs | 無底層設備、動態生成內容、tmpfs 可交換 |
| 偽文件系統 | pipefs, sockfs, bdev, mqueue | 內核內部對象命名空間 |
VFS 以四大對象為核心,將「命名空間操作」(dentry)、「文件元數據」(inode)、「文件系統整體」(super_block)、「打開文件上下文」(file) 清晰分離,並透過緩存層 (dcache、icache、page cache) 橋接高速 CPU 與慢速存儲。理解這套架構,是分析文件系統性能瓶頸、開發新型文件系統、排查掛載/權限/一致性故障的必經之路。