Skip to content

Commit e1d987d

Browse files
committed
添加文件系统框架和部分内容
1 parent b94ec8e commit e1d987d

File tree

5 files changed

+234
-0
lines changed

5 files changed

+234
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"label": "文件系统",
3+
"position": 3,
4+
"link": {
5+
"type": "generated-index"
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
sidebar_position: 1
3+
---
4+
5+
# 文件系统框架
6+
7+
TODO
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
---
2+
sidebar_position: 4
3+
---
4+
5+
## 分区识别机制
6+
7+
ArceOS目前支持两种主流的分区表格式:
8+
9+
#### GPT(GUID分区表)
10+
11+
GPT是现代系统广泛使用的分区表格式,具有以下特点:
12+
13+
- 支持128个主分区
14+
- 使用128位GUID唯一标识分区类型
15+
- 支持分区名称(UTF-16LE编码)
16+
- 包含备份分区表
17+
- 支持CRC32校验
18+
19+
GPT解析过程如下:
20+
21+
1. 读取LBA 1处的GPT头
22+
2. 验证签名("EFI PART")
23+
3. 解析分区项位置和数量
24+
4. 读取分区项数组
25+
5. 提取分区信息
26+
27+
#### MBR(主引导记录)
28+
29+
MBR是传统的分区表格式,虽然功能有限,但仍广泛使用:
30+
31+
- 支持4个主分区
32+
- 使用分区类型标识(1字节)
33+
- 支持扩展分区
34+
35+
当GPT解析失败时,系统会尝试解析MBR分区表,确保向后兼容。
36+
37+
### 分区扫描流程
38+
39+
分区扫描是系统启动时的关键步骤,流程如下:
40+
41+
1. **初始化块设备**:创建`Disk`对象,获取设备信息
42+
2. **尝试GPT解析**:读取GPT头,验证签名
43+
3. **解析分区项**:读取分区项数组,提取分区信息
44+
4. **MBR回退**:如果GPT解析失败,尝试MBR
45+
5. **全盘处理**:如果都没有分区表,将整个磁盘作为单个分区
46+
6. **文件系统检测**:对每个分区进行文件系统类型检测
47+
48+
### 分区信息结构
49+
50+
分区信息通过`PartitionInfo`结构体表示:
51+
52+
```rust
53+
pub struct PartitionInfo {
54+
pub index: u32, // 分区索引(0-based)
55+
pub name: String, // 分区名称
56+
pub partition_type_guid: [u8; 16], // 分区类型GUID
57+
pub unique_partition_guid: [u8; 16], // 唯一分区GUID
58+
pub filesystem_uuid: Option<String>, // 文件系统UUID
59+
pub starting_lba: u64, // 起始LBA
60+
pub ending_lba: u64, // 结束LBA
61+
pub size_bytes: u64, // 分区大小(字节)
62+
pub filesystem_type: Option<FilesystemType>, // 文件系统类型
63+
}
64+
```
65+
66+
这种结构设计包含了分区的所有关键信息,便于上层文件系统使用。
67+
68+
## 文件系统探测机制
69+
70+
### 文件系统类型检测
71+
72+
文件系统类型检测是通过分析分区开始的特定数据结构实现的,目前支持:
73+
74+
#### FAT文件系统检测
75+
76+
FAT文件系统(FAT12/FAT16/FAT32)的检测基于以下特征:
77+
78+
- FAT12/FAT16:在偏移0x36处有"FAT"签名
79+
- FAT32:在偏移0x52处有"FAT32"签名
80+
81+
```rust
82+
fn is_fat_filesystem(boot_sector: &[u8; 512]) -> bool {
83+
// 检查FAT12/FAT16/FAT32签名
84+
if boot_sector.len() >= 0x36 + 3 {
85+
let fat_sig = &boot_sector[0x36..0x36 + 3];
86+
if fat_sig == b"FAT" {
87+
return true;
88+
}
89+
}
90+
91+
if boot_sector.len() >= 0x52 + 5 {
92+
let fat32_sig = &boot_sector[0x52..0x52 + 5];
93+
if fat32_sig == b"FAT32" {
94+
return true;
95+
}
96+
}
97+
98+
false
99+
}
100+
```
101+
102+
检测过程:
103+
104+
1. 读取分区开始的512字节(引导扇区)
105+
2. 检查特定偏移处的签名
106+
3. 确定FAT类型
107+
108+
#### ext4文件系统检测
109+
110+
ext4文件系统的检测基于超级块特征:
111+
112+
- 超级块位于分区偏移1024字节处
113+
- 魔数0xEF53位于超级块偏移1080字节处
114+
115+
```rust
116+
fn is_ext4_filesystem(disk: &mut Disk, start_lba: u64) -> bool {
117+
// ext4超级块位于分区偏移1024字节处
118+
let superblock_offset = start_lba * 512 + 1024;
119+
let mut superblock = [0u8; 2048];
120+
121+
// 保存当前位置
122+
let pos = disk.position();
123+
124+
// 设置位置读取超级块
125+
disk.set_position(superblock_offset);
126+
127+
let result = if let Err(_) = read_exact(disk, &mut superblock) {
128+
warn!("Failed to read ext4 superblock at offset {}", superblock_offset);
129+
false
130+
} else {
131+
// 检查ext4魔数(0xEF53)位于超级块偏移1080字节处
132+
// 由于我们从1024字节处开始读取,魔数位于索引56处
133+
if superblock.len() >= 58 {
134+
let magic = u16::from_le_bytes([superblock[56], superblock[57]]);
135+
magic == 0xEF53
136+
} else {
137+
false
138+
}
139+
};
140+
141+
// 恢复位置
142+
disk.set_position(pos);
143+
144+
result
145+
}
146+
```
147+
148+
检测过程:
149+
150+
1. 定位到超级块位置
151+
2. 读取超级块数据
152+
3. 验证魔数
153+
154+
### 文件系统UUID读取
155+
156+
为了支持通过UUID挂载文件系统,ArceOS实现了从文件系统超级块读取UUID的功能:
157+
158+
#### ext4 UUID读取
159+
160+
ext4的UUID位于超级块偏移0x68处,共16字节。UUID的存储格式为:
161+
162+
- 前3个字段:小端序
163+
- 后2个字段:大端序
164+
165+
读取后转换为标准UUID格式(8-4-4-4-12)。
166+
167+
#### FAT32 UUID读取
168+
169+
FAT32没有标准UUID,但有卷标ID(Volume ID),位于引导扇区偏移0x43处,共4字节。读取后格式化为8字符十六进制字符串。
170+
171+
### 文件系统创建
172+
173+
对于检测到的文件系统,ArceOS会创建对应的文件系统实例:
174+
175+
1. **创建分区包装器**:将分区包装为文件系统可访问的设备
176+
2. **初始化文件系统**:调用文件系统的初始化函数
177+
3. **创建根节点**:创建文件系统的根目录节点
178+
4. **注册到VFS**:将文件系统注册到虚拟文件系统
179+
180+
181+
182+
## 启动流程与挂载策略
183+
184+
### 系统启动流程
185+
186+
文件系统的初始化是系统启动的关键步骤,流程如下:
187+
188+
1. **设备初始化**:初始化块设备驱动
189+
2. **分区扫描**:扫描并识别分区
190+
3. **文件系统检测**:检测各分区的文件系统类型
191+
4. **根文件系统选择**:根据启动参数或默认策略选择根文件系统
192+
5. **文件系统挂载**:挂载根文件系统和其他分区
193+
6. **虚拟文件系统挂载**:挂载/dev, /proc, /sys等虚拟文件系统
194+
195+
### 根文件系统选择策略
196+
197+
ArceOS支持多种根文件系统选择策略:
198+
199+
1. **启动参数指定**:通过`root=`参数指定
200+
- `root=/dev/sdaX`:按设备路径指定
201+
- `root=PARTUUID=xxx`:按分区GUID指定
202+
- `root=UUID=xxx`:按文件系统UUID指定
203+
204+
2. **默认策略**:如果没有指定,使用第一个支持的文件系统分区
205+
206+
3. **回退策略**:如果没有支持的文件系统,使用ramfs作为根文
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
sidebar_position: 3
3+
---
4+
5+
# 实际文件系统
6+
7+
TODO

docs/design/arch/filesystem/vfs.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
sidebar_position: 2
3+
---
4+
5+
# 虚拟文件系统
6+
7+
TODO

0 commit comments

Comments
 (0)