← 项目列表
课程已完成2026年6月

文件系统仿真 — Rust+egui

用 Rust 模拟类 FAT 文件系统,结合 egui 构建跨平台 GUI,位图可视化一目了然。

Rust操作系统文件系统GUIRusteguibit-vec
📋 项目概览
技术栈
Rusteguibit-vec
功能特性
  • 位图磁盘块分配与回收
  • 多级目录树(创建/删除/重命名)
  • 文件 CRUD,动态长度增长
  • egui 实时可视化磁盘状态
  • 交互式 Shell 命令行界面
🚀 在线演示新窗口打开 ↗
💻 核心代码Rust · egui · bit-vec
rust磁盘块管理(Disk)disk.rs · 58 行

使用位图管理 512 个磁盘块的分配与回收。磁盘以 1024 字节为块大小,通过位图标记空闲/占用状态。

use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};

pub const BLOCK_SIZE: usize = 1024;
pub const NUM_BLOCKS: usize = 512;
pub const BOOT_BLOCK: usize = 0;   // 引导块
pub const SUPER_BLOCK: usize = 1;  // 超级块
pub const MFD_BLOCK: usize = 2;    // 主文件目录
pub const UFD_START: usize = 3;    // 用户文件目录
pub const UFD_END: usize = 34;
pub const DATA_START: usize = 35;  // 数据区起点

pub struct Disk {
    file: File,
    pub num_blocks: usize,
    pub block_size: usize,
}

impl Disk {
    pub fn new(path: &str) -> Result<Self, String> {
        let file = OpenOptions::new()
            .read(true).write(true).create(true)
            .open(path)
            .map_err(|e| format!("Failed to open disk file: {}", e))?;
        file.set_len((NUM_BLOCKS * BLOCK_SIZE) as u64)
            .map_err(|e| format!("Failed to set disk size: {}", e))?;
        Ok(Disk { file, num_blocks: NUM_BLOCKS, block_size: BLOCK_SIZE })
    }

    pub fn read_block(&mut self, block_num: usize) -> Result<Vec<u8>, String> {
        if block_num >= self.num_blocks {
            return Err(format!("Block {} out of range (max {})", block_num, self.num_blocks));
        }
        let offset = (block_num * self.block_size) as u64;
        self.file.seek(SeekFrom::Start(offset))
            .map_err(|e| format!("Seek error: {}", e))?;
        let mut buf = vec![0u8; self.block_size];
        self.file.read_exact(&mut buf)
            .map_err(|e| format!("Read error: {}", e))?;
        Ok(buf)
    }

    pub fn write_block(&mut self, block_num: usize, data: &[u8]) -> Result<(), String> {
        if block_num >= self.num_blocks {
            return Err(format!("Block {} out of range (max {})", block_num, self.num_blocks));
        }
        if data.len() != self.block_size {
            return Err(format!("Data size {} != block size {}", data.len(), self.block_size));
        }
        let offset = (block_num * self.block_size) as u64;
        self.file.seek(SeekFrom::Start(offset))
            .map_err(|e| format!("Seek error: {}", e))?;
        self.file.write_all(data)
            .map_err(|e| format!("Write error: {}", e))?;
        self.file.flush().map_err(|e| format!("Flush error: {}", e))?;
        Ok(())
    }
}
rust文件系统核心(FS)fs.rs · 57 行

文件系统核心逻辑,包括目录项管理、主文件目录(MFD)、用户文件目录(UFD)。支持登录验证、文件操作。

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct DirEntry {
    pub name: [u8; MAX_FILENAME],   // 28 字节文件名
    pub type_: i32,                  // 0=文件, 1=目录
    pub start_block: i32,            // 起始块号
    pub size: i32,                   // 文件大小
    pub password: [u8; MAX_PASSWORD],// 16 字节密码
    pub create_time: i64,            // 创建时间戳
}

impl DirEntry {
    pub fn new(name: &str, type_: i32, password: &str) -> Self {
        let mut entry = DirEntry {
            name: [0u8; MAX_FILENAME], type_, start_block: -1,
            size: 0, password: [0u8; MAX_PASSWORD],
            create_time: SystemTime::now()
                .duration_since(UNIX_EPOCH).unwrap().as_secs() as i64,
        };
        let name_bytes = name.as_bytes();
        let len = name_bytes.len().min(MAX_FILENAME - 1);
        entry.name[..len].copy_from_slice(&name_bytes[..len]);
        // ... password similarly ...
        entry
    }

    pub fn name_str(&self) -> String {
        let end = self.name.iter().position(|&b| b == 0)
            .unwrap_or(self.name.len());
        String::from_utf8_lossy(&self.name[..end]).to_string()
    }

    pub fn is_empty(&self) -> bool {
        self.name[0] == 0 || self.name_str().is_empty()
    }
}

pub struct Session {
    pub current_user: Option<String>,
}

impl Session {
    pub fn new() -> Self { Session { current_user: None } }

    pub fn login(&mut self, disk: &mut Disk, username: &str, password: &str) -> Result<(), String> {
        // 读取 MFD 块,验证用户名密码
        let data = disk.read_block(MFD_BLOCK)?;
        let mfd: MasterDirectory = unsafe { std::mem::transmute(data) };
        for user in &mfd.users[..mfd.user_count as usize] {
            if user.name_str() == username && user.password_str() == password {
                self.current_user = Some(username.to_string());
                return Ok(());
            }
        }
        Err("用户名或密码错误".to_string())
    }
}
rustegui 图形界面(App)app.rs · 59 行

基于 egui 构建的交互式 GUI,包含命令终端、磁盘状态可视化和实时反馈。

use eframe::egui;
use egui::Color32;

pub struct FileSystemApp {
    pub session: Session,
    pub disk: Option<Disk>,
    pub disk_state: DiskState,
    pub output_lines: Vec<(String, Color32)>,
    pub input_buffer: String,
    pub selected_block: Option<usize>,
}

impl Default for FileSystemApp {
    fn default() -> Self {
        Self {
            session: Session::new(),
            disk: None,
            disk_state: DiskState::default(),
            output_lines: vec![
                ("💾 二级文件系统仿真 — Rust + egui".to_string(), Color32::from_rgb(86, 156, 214)),
                ("输入 help 查看可用命令,format <文件名> 开始使用".to_string(), Color32::from_rgb(128, 128, 128)),
            ],
            input_buffer: String::new(),
            selected_block: None,
        }
    }
}

impl eframe::App for FileSystemApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::TopBottomPanel::top("terminal").show(ctx, |ui| {
            ui.horizontal(|ui| {
                let input = egui::TextEdit::singleline(&mut self.input_buffer)
                    .desired_width(f32::INFINITY)
                    .hint_text("> 输入命令...")
                    .show(ui);
                if ui.button("⏎").clicked() || input.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter)) {
                    self.execute_current_command();
                }
            });
        });

        egui::CentralPanel::default().show(ctx, |ui| {
            // Left: terminal output
            egui::SidePanel::left("output")
                .resizable(true)
                .default_width(400.0)
                .show_inside(ui, |ui| {
                    egui::ScrollArea::vertical().stick_to_bottom(true).show(ui, |ui| {
                        for (text, color) in &self.output_lines {
                            ui.colored_label(*color, text);
                        }
                    });
                });
            // Right: disk visualization
            self.render_disk_map(ui);
        });
    }
}
📁 源文件清单
路径说明行数
src/disk.rs磁盘块设备模拟(512块×1024字节)72
src/fs.rs文件系统核心(MFD/UFD/目录项)210
src/app.rsegui 图形界面应用180
src/shell.rs命令解析与执行150
src/visual.rs磁盘状态可视化渲染85
src/main.rs程序入口40
tests/integration_test.rs集成测试95
网站智能助手
💬 和我聊聊
🤖
你好呀 👋 有什么想聊的?