os/fs/
smfs.rs

1//! 一个简单的内存文件系统(MemFS)实现。
2//!
3//! 在这个文件系统中,所有文件都嵌入在内核的只读数据段中,
4//! 以静态字节切片的形式存在。
5//! 在实现真正的文件系统之前,这个模块为用户程序提供了基本的存储功能。
6use alloc::string::String;
7use alloc::vec::Vec;
8
9/// 描述简单内存文件系统的单个文件条目。
10pub struct FileEntry {
11    /// 文件名,通常是 UTF-8 字符串
12    pub name: &'static str,
13    /// 文件的内容,作为静态字节切片嵌入
14    pub data: &'static [u8],
15    /// 文件大小(冗余字段,但方便快速访问)
16    pub size: usize,
17}
18
19/// 简单内存文件系统的主要结构,包含所有静态文件条目。
20pub struct SimpleMemoryFileSystem {
21    files: &'static [FileEntry],
22}
23
24// 对齐包装类型:将嵌入的字节数组强制为 8 字节对齐
25#[repr(align(8))]
26struct Align8<const N: usize>([u8; N]);
27
28// 用 include_bytes! 宏将编译好的用户程序嵌入到这里
29const INIT: Align8<{ include_bytes!("../../../user/bin/init").len() }> =
30    Align8(*include_bytes!("../../../user/bin/init"));
31static HELLO: Align8<{ include_bytes!("../../../user/bin/hello").len() }> =
32    Align8(*include_bytes!("../../../user/bin/hello"));
33
34/// 静态文件列表:这是 MemFS 的核心存储
35static STATIC_FILES: [FileEntry; 2] = [
36    FileEntry {
37        name: "init",
38        data: &INIT.0,
39        size: INIT.0.len(),
40    },
41    FileEntry {
42        name: "hello",
43        data: &HELLO.0,
44        size: HELLO.0.len(),
45    },
46];
47
48// 这是为了通过cargo check,实际使用时请仿照上示代码将文件添加进来
49// static STATIC_FILES: [FileEntry; 0] = [];
50
51impl SimpleMemoryFileSystem {
52    /// # 函数:init
53    /// 初始化内存文件系统。
54    pub const fn init() -> Self {
55        Self {
56            files: &STATIC_FILES,
57        }
58    }
59
60    /// # 函数:lookup
61    /// 根据文件名查找文件的内容切片。
62    ///
63    /// @param name - 要查找的文件名。
64    /// @returns - 如果找到,返回文件的内容切片;否则返回 None。
65    pub fn lookup(&self, name: &str) -> Option<&'static [u8]> {
66        self.files
67            .iter()
68            .find(|entry| entry.name == name)
69            .map(|entry| entry.data)
70    }
71
72    /// # 函数:list_all
73    /// 获取所有文件的名称列表。
74    pub fn list_all(&self) -> Vec<String> {
75        self.files
76            .iter()
77            .map(|entry| String::from(entry.name))
78            .collect()
79    }
80
81    /// # 辅助函数:load_elf
82    /// 这是供进程创建使用的主要接口。
83    ///
84    /// @param name - ELF 文件名。
85    /// @returns - ELF 二进制数据的字节切片。
86    pub fn load_elf(&self, name: &str) -> Option<&'static [u8]> {
87        self.lookup(name)
88    }
89}