os/vfs/
mod.rs

1//! 虚拟文件系统(VFS)层
2//!
3//! 该模块提供了一个 **POSIX 兼容的虚拟文件系统抽象**,支持多种文件类型和文件系统的统一访问。
4//!
5//! # 组件
6//!
7//! - [`mod@file`] - 会话层接口定义 (File trait)
8//! - [`inode`] - 存储层接口定义 (Inode trait)
9//! - [`dentry`] - 目录项结构和全局缓存
10//! - [`path`] - 路径解析引擎(绝对/相对路径、符号链接)
11//! - [`mount`] - 挂载表管理和挂载点栈
12//! - [`fd_table`] - 进程级文件描述符表
13//! - [`file_lock`] - POSIX 文件锁管理器
14//! - [`file_system`] - 文件系统抽象接口
15//! - [`impls`] - 具体文件类型实现(RegFile、PipeFile 等)
16//! - [`error`] - VFS 错误类型定义
17//! - [`dev`]/[`devno`] - 设备号管理和驱动注册
18//!
19//! # 设计概览
20//!
21//! ## 分层架构
22//!
23//! VFS 采用四层架构设计,从上到下依次为:
24//!
25//! 1. **应用层**:系统调用接口和文件描述符表 ([`FDTable`])
26//! 2. **会话层**:有状态的文件操作接口 ([`File`] trait),维护 offset 和 flags
27//! 3. **路径层**:目录树管理和路径解析 ([`Dentry`]、[`path`] 模块)
28//! 4. **存储层**:无状态的存储访问接口 ([`Inode`] trait)
29//!
30//! ## 核心设计理念
31//!
32//! ### 分离会话与存储
33//!
34//! - **会话层 (File)**:每次 `open()` 创建新的 `File` 实例,维护独立的 `offset` 和 `flags`
35//! - **存储层 (Inode)**:多个 `File` 可共享同一个 `Inode`,实现硬链接和 dup 语义
36//!
37//! ```text
38//! fd[3] ──┐
39//!         ├──> Arc<RegFile> { offset: 100, ... }
40//! fd[4] ──┘                     │
41//!                               │
42//!                               ▼
43//!                          Arc<Dentry>
44//!                               │
45//!                               ▼
46//!                          Arc<dyn Inode>
47//! ```
48//!
49//! ### 目录项缓存
50//!
51//! - **全局缓存** ([`DENTRY_CACHE`]):路径 → `Weak<Dentry>` 映射,避免重复解析
52//! - **树状缓存**:Dentry 内部维护父子关系,加速相对路径查找
53//! - **自动失效**:使用 `Weak` 引用,不再使用的 Dentry 自动回收
54//!
55//! ### 挂载表管理
56//!
57//! - **最长前缀匹配**:访问 `/mnt/data/file` 时自动选择最匹配的挂载点
58//! - **挂载点栈**:同一路径可多次挂载,最后挂载的文件系统覆盖前面的
59//! - **全局单例** ([`MOUNT_TABLE`]):所有挂载点的集中管理
60//!
61//! ## 性能特点
62//!
63//! - **零拷贝读写**:RegFile 直接调用 Inode 的 `read_at`/`write_at`,无额外拷贝
64//! - **原子偏移量**:使用 `AtomicUsize` 管理文件偏移,无锁并发读写
65//! - **多级缓存**:Dentry 缓存、挂载点缓存减少重复查找
66//! - **引用计数**:使用 `Arc`/`Weak` 自动管理对象生命周期,无需手动释放
67//!
68//! ## 并发安全
69//!
70//! - **FDTable**:内部使用 `SpinLock` 保护文件描述符数组
71//! - **DentryCache**:使用 `SpinLock` 保护全局缓存
72//! - **MountTable**:使用 `SpinLock` 保护挂载表
73//! - **FileLockManager**:使用 `SpinLock` 保护文件锁表
74//!
75//! # 文件类型
76//!
77//! VFS 支持多种文件类型,所有类型都实现统一的 [`File`] trait:
78//!
79//! - [`RegFile`]: 普通文件 - 基于 Inode,支持 seek
80//! - [`PipeFile`]: 管道文件 - 环形缓冲区,流式设备
81//! - [`StdinFile`]/[`StdoutFile`]/[`StderrFile`]: 标准 I/O 文件
82//! - `CharDevFile`: 字符设备文件(串口、终端等)
83//! - `BlkDevFile`: 块设备文件(磁盘等)
84//!
85//! # 使用示例
86//!
87//! ## 基本文件操作
88//!
89//! ```rust
90//! use vfs::{vfs_lookup, RegFile, OpenFlags};
91//! use alloc::sync::Arc;
92//!
93//! // 1. 查找文件
94//! let dentry = vfs_lookup("/etc/passwd")?;
95//!
96//! // 2. 创建 File 对象
97//! let file = Arc::new(RegFile::new(dentry, OpenFlags::O_RDONLY));
98//!
99//! // 3. 读取数据
100//! let mut buf = [0u8; 1024];
101//! let n = file.read(&mut buf)?;
102//! ```
103//!
104//! ## 使用文件描述符
105//!
106//! ```rust
107//! // 分配文件描述符
108//! let fd_table = current_task().lock().fd_table.clone();
109//! let fd = fd_table.alloc(file)?;
110//!
111//! // 通过 FD 访问文件
112//! let file = fd_table.get(fd)?;
113//! file.read(&mut buf)?;
114//!
115//! // 关闭文件
116//! fd_table.close(fd)?;
117//! ```
118//!
119//! ## 挂载文件系统
120//!
121//! ```rust
122//! use vfs::{MOUNT_TABLE, MountFlags};
123//!
124//! // 创建文件系统
125//! let tmpfs = Arc::new(TmpFs::new());
126//!
127//! // 挂载到 /tmp
128//! MOUNT_TABLE.mount(tmpfs, "/tmp", MountFlags::empty(), None)?;
129//!
130//! // 访问挂载点下的文件
131//! let dentry = vfs_lookup("/tmp/test.txt")?;
132//!
133//! // 卸载
134//! MOUNT_TABLE.umount("/tmp")?;
135//! ```
136//!
137//! ## 创建管道
138//!
139//! ```rust
140//! use vfs::PipeFile;
141//!
142//! let (read_file, write_file) = PipeFile::create_pipe()?;
143//!
144//! // 分配文件描述符
145//! let read_fd = fd_table.alloc(read_file)?;
146//! let write_fd = fd_table.alloc(write_file)?;
147//!
148//! // 父子进程通过管道通信
149//! ```
150
151pub mod adapter;
152pub mod dentry;
153pub mod dev;
154pub mod devno;
155pub mod error;
156pub mod fd_table;
157pub mod file;
158pub mod file_lock;
159pub mod file_system;
160pub mod impls;
161pub mod inode;
162pub mod mount;
163pub mod path;
164
165pub use adapter::inode_type_to_d_type;
166pub use dentry::{DENTRY_CACHE, Dentry, DentryCache};
167pub use dev::{major, makedev, minor};
168pub use devno::{get_blkdev_index, get_chrdev_driver};
169pub use error::FsError;
170pub use fd_table::FDTable;
171pub use file::File;
172pub use file_lock::file_lock_manager;
173pub use file_system::{FileSystem, StatFs};
174pub use impls::{PipeFile, RegFile, StderrFile, StdinFile, StdoutFile, create_stdio_files};
175pub use inode::{DirEntry, FileMode, Inode, InodeMetadata, InodeType};
176pub use mount::{MOUNT_TABLE, MountFlags, MountPoint, MountTable, get_root_dentry};
177pub use path::{
178    normalize_path, parse_path, split_path, vfs_lookup, vfs_lookup_from, vfs_lookup_no_follow,
179};
180
181// Re-export UAPI types used by VFS
182pub use crate::uapi::fcntl::{FdFlags, OpenFlags, SeekWhence};
183pub use crate::uapi::fs::{LinuxDirent64, Stat};
184pub use crate::uapi::time::TimeSpec;
185
186use alloc::{vec, vec::Vec};
187
188/// 从指定路径加载 ELF 文件内容
189///
190/// 参数:
191///     - path: 文件路径(绝对路径或相对于当前工作目录的相对路径)
192///
193/// 返回:`Ok(Vec<u8>)` 文件内容字节数组;`Err(FsError::NotFound)` 文件不存在;`Err(FsError::IsDirectory)` 路径指向目录
194pub fn vfs_load_elf(path: &str) -> Result<Vec<u8>, FsError> {
195    let dentry = vfs_lookup(path)?;
196    let inode = &dentry.inode;
197    let metadata = inode.metadata()?;
198
199    // 确保是普通文件
200    if metadata.inode_type != InodeType::File {
201        return Err(FsError::IsDirectory);
202    }
203
204    let mut buf = vec![0u8; metadata.size];
205    inode.read_at(0, &mut buf)?;
206    Ok(buf)
207}
208
209#[cfg(test)]
210mod tests;