从零写OS内核201:存储系统-VFS 篇:为自制 OS 设计统一文件抽象层
“在自制操作系统中,如何让 open/read/write 既能操作 ext2,又能操作 procfs? 本文将从零设计 VFS 抽象层,构建四大核心对象,实现路径解析与缓存机制, 为后续文件系统提供统一接口。”
引言:为什么自制 OS 需要 VFS?
在自制操作系统中,初期可能只实现一个文件系统(如 ext2)。 但随着系统演进,你将需要:
procfs
:暴露内核信息(/proc/cpuinfo)
sysfs
:管理设备(/sys/devices)
devfs
:设备文件(/dev/tty0)
tmpfs
:内存文件系统
如果每个文件系统都直接暴露 ext2_open 、 proc_open 接口, 用户程序将不得不 硬编码文件系统类型 ,系统扩展性极差。
VFS (Virtual File System)正是为解决此问题而生! 它通过 统一抽象层 ,让上层应用只需调用 open(path) , VFS 自动路由到对应文件系统的实现。
本文将为自制 OS 设计一个 简洁高效、易于扩展 的 VFS 框架。
第一章:VFS 核心设计原则
1.1 设计目标
核心目标:
- 统一接口
:用户程序无需关心文件系统类型
-
易于扩展
:新增文件系统只需实现 VFS 接口
-
性能优先
:路径解析 O(log n),缓存加速
-
内存高效
:对象按需分配,支持回收
约束条件:
32 位系统
:指针对齐 4 字节
无动态加载
:文件系统编译时注册
单核设计
:暂不考虑锁(后续可扩展)
1.2 架构概览
1.3 关键设计决策
四大核心对象(简化版):
| 对象 | 职责 | 生命周期 |
|---|---|---|
| vfs_super | 描述文件系统实例 | 挂载时创建,卸载时销毁 |
| vfs_inode | 描述单个文件 | 首次访问时创建,LRU 回收 |
| vfs_dentry | 缓存路径名到 inode 映射 | 路径解析时创建,LRU 回收 |
| vfs_file | 描述打开的文件 | open 时创建,close 时销毁 |
路径解析策略:
dentry 缓存
:哈希表加速查找
按需加载
:inode 仅在需要时创建
路径组件解析
:从根目录逐级查找
缓存管理:
LRU 链表
:管理未使用的 dentry/inode
内存压力回收
:空闲内存低于阈值时触发
第二章:VFS 核心数据结构
2.1 vfs_super:文件系统实例
2.2 vfs_inode:文件元数据
2.3 vfs_dentry:路径名缓存
2.4 vfs_file:打开的文件
第三章:VFS 核心流程实现
3.1 文件系统注册
文件系统类型
注册宏
使用示例(ext2)
3.2 路径解析:vfs_path_lookup
主流程
dentry 查找(d_lookup)
3.3 dentry 缓存管理
d_add:添加 dentry 到缓存
dentry 回收
第四章:系统调用对接
4.1 open 系统调用
4.2 read/write 系统调用
第五章:内存与性能优化
5.1 LRU 缓存回收策略
触发条件:
内存分配失败
:buddy_alloc 返回 NULL
定期回收
:时钟中断定期检查
回收顺序:
- dentry 缓存
:无引用的 dentry
-
inode 缓存
:无引用的 inode
-
页缓存
:后续实现
5.2 哈希表优化
动态扩容(简化版):
5.3 路径解析优化
路径组件缓存:
栈分配
:小路径使用栈缓冲区
避免重复解析
:缓存完整路径结果
结论:为自制 OS 构建可扩展存储栈
VFS 是自制操作系统 存储子系统的基石* 。 通过精心设计的四大对象和缓存机制, 我们实现了:
统一接口
:用户程序无需关心底层文件系统
易于扩展
:新增文件系统只需实现 VFS 接口
性能保障
:dentry 缓存加速路径解析
内存高效
:LRU 回收机制避免内存泄漏
此 VFS 框架为后续实现 ext2、procfs、sysfs、devfs 奠定了坚实基础。 每新增一个文件系统,只需:
- 实现
vfs_super_operations - 实现
vfs_inode_operations
和
vfs_file_operations - 使用
VFS_DECLARE_FILESYSTEM
注册
真正的操作系统,始于对抽象的深刻理解。 VFS 正是这种抽象能力的完美体现。
附录:关键数据结构与接口速查
核心数据结构
| 结构 | 作用 |
|---|---|
| struct vfs_super | 文件系统实例 |
| struct vfs_inode | 文件元数据 |
| struct vfs_dentry | 路径名缓存 |
| struct vfs_file | 打开的文件 |
文件系统注册
路径解析
系统调用
注 :本文所有代码均为简化实现,实际使用需添加错误处理、边界检查等。
评论