虚拟文件系统(VFS)
一、VFS 的角色
VFS(Virtual File System)是 Linux 内核对所有文件系统的抽象层:
- 统一接口(open/read/write/...)
- 上层(应用)透明
- 下层对接各种具体文件系统(ext4、vfat、proc、sysfs、...)
┌──────────────────────────┐
│ 用户态:open/read/write │
├──────────────────────────┤
│ VFS(file_operations) │
├──────────────────────────┤
│ 具体文件系统(ext4...) │
├──────────────────────────┤
│ 通用块层 / 网络层 │
├──────────────────────────┤
│ 设备驱动 │
└──────────────────────────┘
二、四大对象
1. super_block(超级块)
- 一个挂载的文件系统
- 包含文件系统元信息(大小、块大小、统计)
struct super_block *sb;
2. inode(索引节点)
- 一个文件(或目录、设备)
- 包含元数据(大小、权限、时间、块位置)
- 不包含文件名
struct inode *inode;
3. dentry(目录项)
- 文件名 → inode 的映射
- 缓存作用(dcache)
- 树形结构
struct dentry *dentry;
4. file(打开文件)
- 一个进程打开一个文件的实例
- 文件位置、flags、私有数据
struct file *file;
四对象关系:
进程 fd_table
↓
[fd] → struct file
↓
struct dentry
↓
struct inode
↓
struct super_block
三、关键结构
struct file_operations {
struct module *owner;
loff_t (*llseek)(struct file *, loff_t, int);
ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
int (*mmap)(struct file *, struct vm_area_struct *);
int (*open)(struct inode *, struct file *);
int (*release)(struct inode *, struct file *);
int (*fsync)(struct file *, loff_t, loff_t, int);
// ...
};
struct inode_operations {
int (*create)(struct inode *, struct dentry *, umode_t, bool);
struct dentry *(*lookup)(struct inode *, struct dentry *, unsigned);
int (*link)(struct dentry *, struct inode *, struct dentry *);
int (*unlink)(struct inode *, struct dentry *);
int (*mkdir)(struct inode *, struct dentry *, umode_t);
// ...
};
struct super_operations {
struct inode *(*alloc_inode)(struct super_block *);
void (*destroy_inode)(struct inode *);
void (*write_super)(struct super_block *);
int (*sync_fs)(struct super_block *, int);
int (*remount_fs)(struct super_block *, int *, char *);
void (*put_super)(struct super_block *);
// ...
};
四、注册文件系统
#include <linux/fs.h>
static struct file_system_type my_fs_type = {
.owner = THIS_MODULE,
.name = "myfs",
.mount = myfs_mount,
.kill_sb = myfs_kill_sb,
.fs_flags = FS_USERNS_MOUNT,
};
register_filesystem(&my_fs_type);
unregister_filesystem(&my_fs_type);
挂载:
mount -t myfs none /mnt/myfs
五、注册字符设备
详见 09-char-device.md。
六、调试 VFS
# /proc/filesystems:已注册文件系统
# /proc/mounts:挂载点
cat /proc/mounts
mount
findmnt
# dcache 状态
cat /proc/sys/fs/dentry-state
# inode 状态
cat /proc/sys/fs/inode-state
# 调试特定 inode
debugfs/.../inode_dump
七、嵌入式常用文件系统
| FS | 用途 |
|---|---|
| ext4 | 通用 |
| vfat | U盘、SD卡启动 |
| tmpfs | /tmp、/run |
| devtmpfs | /dev |
| procfs | /proc |
| sysfs | /sys |
| squashfs | 压缩只读 rootfs |
| jffs2 / ubifs | NAND 闪存 |
| overlayfs | OTA、容器 |
| f2fs | eMMC 优化 |
八、文件系统挂载流程
mount -t ext4 /dev/mmcblk0p2 /mnt
↓
sys_mount → do_mount → do_new_mount
↓
vfs_kern_mount(...)
↓
alloc_super → fill_super(读磁盘填充 sb)
↓
分配根 inode 和 dentry
↓
挂载成功
九、O_DIRECT / O_SYNC
O_DIRECT:绕过页缓存,直接读写(数据库常用)O_SYNC / O_DSYNC:每次写都同步到磁盘- 对延迟影响大,需谨慎
十、buffer_head 与 bio
- buffer_head (bh):传统方式,单块缓冲
- bio:现代方式,可多个块,便于 merge、splite
- 块设备驱动现在用 bio