Expand description
文件抽象层 - VFS 会话层接口
该模块定义了统一的文件操作接口 File trait,支持普通文件、管道、字符设备等多种文件类型。
所有打开的文件以 Arc<dyn File> 形式存储在进程的文件描述符表中。
§架构定位
VFS 采用两层设计:
§为什么分离会话层和存储层?
同一个文件可以被多次打开或 dup,每次打开都需要独立的会话状态(如 offset), 但它们共享相同的底层存储(Inode)。这种设计支持:
- dup 语义: 复制的文件描述符共享 offset
- 硬链接: 多个路径指向同一个 Inode
- fork 继承: 父子进程共享文件表
进程 A: fd[3] ──┐
├──> Arc<RegFile> { offset: 100 }
进程 A: fd[4] ──┘ │
▼
Arc<Dentry>
│
▼
Arc<Inode> ←─── 进程 B: fd[5] -> Arc<RegFile> { offset: 200 }§实现类型
RegFile- 普通文件,基于 Inode,支持 seekPipeFile- 管道,环形缓冲区,流式设备StdinFile/StdoutFile/StderrFile- 标准 I/OCharDevFile- 字符设备文件(串口、终端等)BlkDevFile- 块设备文件(磁盘等)
§设计特点
§可选方法
File trait 中的许多方法提供了默认实现(返回 NotSupported),
允许不同文件类型只实现自己支持的功能:
lseek(): 仅 RegFile 和 BlkDevFile 支持get_pipe_size(): 仅 PipeFile 支持ioctl(): 仅设备文件支持
§原子操作
RegFile 使用 AtomicUsize 管理 offset,支持无锁并发读写:
线程 1: read() -> fetch_add(n)
线程 2: read() -> fetch_add(m) // 并发安全§使用示例
use vfs::{vfs_lookup, RegFile, OpenFlags, File};
use alloc::sync::Arc;
// 1. 创建 File 对象
let dentry = vfs_lookup("/etc/passwd")?;
let file: Arc<dyn File> = Arc::new(
RegFile::new(dentry, OpenFlags::O_RDONLY)
);
// 2. 读取数据
let mut buf = [0u8; 1024];
let n = file.read(&mut buf)?;
// 3. 检查文件属性
assert!(file.readable());
assert!(!file.writable());
// 4. 获取元数据
let metadata = file.metadata()?;
println!("文件大小: {}", metadata.size);Traits§
- File
- 文件操作的统一接口