From 1ddda30ab8f4e44bea3b9af419de47ff62747ef0 Mon Sep 17 00:00:00 2001 From: xmin Date: Fri, 8 Nov 2024 14:57:05 +0800 Subject: [PATCH 1/2] =?UTF-8?q?add=202024=E7=A7=8B=E5=86=AC=E5=AD=A3?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E6=80=BB=E7=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...66\346\256\265\346\200\273\347\273\223.md" | 22 + ...66\346\256\265\346\200\273\347\273\223.md" | 1044 +++++++++++++++++ ...0\345\270\203\345\261\200\345\233\276.svg" | 1 + 3 files changed, 1067 insertions(+) create mode 100644 "source/_posts/2024\344\270\200\351\230\266\346\256\265\346\200\273\347\273\223.md" create mode 100644 "source/_posts/2024\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223.md" create mode 100644 "source/_posts/2024\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223/2_unit_\345\206\205\345\255\230\345\270\203\345\261\200\345\233\276.svg" diff --git "a/source/_posts/2024\344\270\200\351\230\266\346\256\265\346\200\273\347\273\223.md" "b/source/_posts/2024\344\270\200\351\230\266\346\256\265\346\200\273\347\273\223.md" new file mode 100644 index 00000000000..c578c13c128 --- /dev/null +++ "b/source/_posts/2024\344\270\200\351\230\266\346\256\265\346\200\273\347\273\223.md" @@ -0,0 +1,22 @@ +--- +title: 2024一阶段总结 +date: 2024-11-07 22:59:43 +tags: +--- + +# 2024一阶段总结 + +由于我在暑假期间花了十几天时间学习了一下Rust,所以在这一阶段期间我就是相当于直接做题了,没什么可说的。但是,第一阶段也是Rust学习阶段,那么这样来说,这一阶段也就不仅仅是那三个星期,还包括了暑假期间的学习。所以,我就把这一阶段的总结写在这里。 + +## Rust学习 +我首先双语对照阅读了《Programming Rust 2nd》这本书。这本书是我在暑假期间学习Rust的主要资料。这本书它好像比较关注底层的内存模型,并在一些方面比较了和C++的区别,它好像特别强调了Rust的系统编程这一方面,所以它关注前面那些方面也就是可以理解的了。 + +由于我在学习Rust之前学了一些函数式编程的习惯知识(比较浅),学习了一下通过《Get Programming with Haskell》这本书学习了一下Haskell,所以在学习Rust时,遇到迭代器、闭包、trait、类型系统、Enum(和类型)等等这些概念时,感觉比较亲切。特别是返回值的Option和Result以及它们与模式匹配的结合,我在Haskell的学习中也常常遇到。 + +在学习Rust的过程中,对C的学习和对C++的浅浅尝试帮助了我对Rust的底层数据模型的理解,而对Java和Haskell的学习,则帮助了我对Rust中的一些类似面向对象、函数式的高层抽象的学习。 + +在阅读一些英文书时,我习惯双语对照着看,看中文效率更高,但经过一层翻译,可能意思有所变化;而看英文则更准确,但效率较低。所以我当时结合着看,看中文卡着了,就去翻翻英文;看英文,由于我的英语不太好,可能有些模糊不清,就去看看中文。此外,有时看一种语言看烦了,可以换另一种语言看看,同样有新鲜感。在浏览器中,要双语对照,可以用插件(如“沉浸式翻译”等);对于pdf、epub之类的,我就用的一个网站[https://doc2x.noedgeai.com/](https://doc2x.noedgeai.com/),识别效果还不错,翻译也还行,虽然现在好像开始收费了。 + +## 一阶段的做题 + +这一阶段做的是Rustlings的题目。这个题目在我刚刚学习入门玩Rust时做了一下,所以前 100 题比较顺利。但是,在最后十题卡了几下,有对数据结构、算法的遗忘,也有对在其中用到的一些在safe边缘疯狂试探的Rust相关语法、特性的生疏。这些题目让我复习了一下数据结构与算法,并让我得以一窥Rust的一些底层方面的高级特性。 \ No newline at end of file diff --git "a/source/_posts/2024\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223.md" "b/source/_posts/2024\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223.md" new file mode 100644 index 00000000000..965629b8645 --- /dev/null +++ "b/source/_posts/2024\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223.md" @@ -0,0 +1,1044 @@ +--- +title: 2024二阶段总结 +date: 2024-11-08 11:22:39 +tags: +--- + +# 2024二阶段总结 + +在这一阶段,我对我的学习可以划分两个比较明显的时期,一个是前期比较懵懂地入门,一个是中后期的速通。 + +## 入门 + +刚刚接触时我是懵逼的、接触了几天后我是迷茫的,看了前两章后,有不少地方还是不太明白,我意识到我对一些相关知识的掌握是非常欠缺的。所以我暂停了一下。 + +在暂停后,我找了一些相关的资料(如riscv reader即riscv开放架构之道、riscv体系结构与实践,看了一些相关的视频(如plct lab放在B站上的[循序渐进,学习开发一个 RISC-V 上的操作系统](https://gitee.com/unicornx/riscv-operating-system-mooc)mooc,mooc看完了,书没有看完。 + +在对一些相关的知识有了一些了解。然后我又回到了rCore上,我重新审视了前两章,学习了第三章,并在前三章分别画了一些序列图、c4图、类图等十几张图,帮助我梳理与理解,为后面的学习打下了基础。 + +## 速通 + +接着,经过前面的时间消耗,所剩时间已经不多了,而且新知识可能忘的会比较快,所以在我看来已经堪堪入门后,就开始了速通(当然,这里的速通是相对于前三章而言的,不是各位大佬眼里的速通,是入门改)。 + +rCore每一章都是循序渐进的,我在每一章中花的时间主要是在文档的阅读和对系统架构、代码的理解上,花在lab上的时间反而并不多,仅有的在lab上卡住的几次,也大多由于看错题、粗心漏掉一些东西。 + +这一时期基本上就是看文档、做lab、看文档、做lab,如此循环,两点一线 -- 学习的乏味。 + +## 一些图 + +这些图有的可能有点不太对,但应该也差不了多少。 + +### 第一章 + +```plantuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml + +Container(os, "os", "crate", "kernel") +' Container(sbi, "sbi.rs", "crate", "封装 RustSBI") +Container(rustsbi, "rustsbi", "bin", "") +Container(log, "log", "crate", "日志库") +Container(hart, "hart", "hardware thread", "qemu模拟的硬件线程") + +' Rel(os, app, "启动app") +' Rel(os, riscv, "管理csr寄存器") +' Rel(os, lazy_static, "静态变量初始化") +' Rel(os, sbi, "") +Rel(os, log, "日志输出") +Rel(os, rustsbi, "调用 RustSBI") +Rel(os, hart, "trap") +Rel(hart, rustsbi, "中断处理") + +``` +```plantuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml + +Container_Boundary(os, "os", "kernel"){ + Component(main, "os/src/main.rs", "mod", "操作系统主入口,负责初始化(清理 BSS 段)和启动各个组件") + Component(lang_items, "os/src/lang_items.rs", "mod", "Rust 语言项") + Component(console, "os/src/console.rs", "mod", "负责输出信息") + Component(logging, "os/src/logging.rs", "mod", "日志库封装") + Component(sbi, "os/src/sbi.rs", "mod", "封装 sbi_rs") +} +Lay_L(console, lang_items) +Lay_L(lang_items , logging) + +Container(app, "app", "crate", "应用程序") +Container(sbi_rs, "sbi_rs", "crate", "封装 RustSBI") +Container(rustsbi, "rustsbi", "bin", "RustSBI 的实现") +Container(log, "log", "crate", "日志库") + +BiRel(app, os, "系统调用 \n 启动app") +Rel_D(main, console, "println!()") +Rel_D(main, logging, "init()") +Rel(main, log, "log相关函数") +Rel(console, sbi, "console_putchar() \n console_getchar() \n system_reset()") +Rel(log, console, "println!()") +Rel(sbi, sbi_rs, "调用 RustSBI 的封装") +Rel(sbi_rs, rustsbi, "调用 RustSBI") +Rel(lang_items, sbi, "发生 panic 时调用shutdown()") +``` +```mermaid +--- +config: + theme: neo +--- + +sequenceDiagram + autonumber + participant User + participant Qemu as Qemu Initializer + participant Bootloader as Bootloader
rustsbi-qemu.bin + participant Entry.asm + + box os/src/main.rs + participant rust_main as fn
rust_main + participant clear_bss as fn
clear_bss + end + + participant console as os/src/console.rs + + box os/src/sbi.rs + participant console_putchar as fn
console_putchar + participant shutdown as fn
shutdown + end + + participant sbi_rt as crate
sbi_rt + + box os/src/lang_items.rs + participant lang_items_panic as fn
panic + end + + User->>Qemu: Execute Qemu + Qemu->>Qemu: Initialize virt machine
Load bootloader (rustsbi-qemu.bin) to 0x80000000
Load kernel image (os.bin) to 0x80200000 + Qemu->>Qemu: Set PC to 0x1000 + Qemu->>Qemu: Execute first instruction at 0x1000 + Qemu->>Bootloader: Jump to 0x80000000 + Bootloader->>Bootloader: Initialize somethings + Bootloader->>Entry.asm: Jump to 0x80200000 + Entry.asm->>Entry.asm: Set stack pointer (sp) to boot_stack_top + Entry.asm->>rust_main: Call rust_main + rust_main->>clear_bss: clear_bss() + + rust_main ->> console: println!() + console ->> console: print() + console ->> console_putchar: console_putchar() + console_putchar ->> sbi_rt::console_putchar() + + rust_main ->> shutdown: shutdown() + shutdown ->> sbi_rt: system_reset() + + opt when panic + lang_items_panic ->> shutdown: shutdown() + end +``` + +### 第二章 + +{% asset_img <2_unit_内存布局图.svg> <2_unit_内存布局图> %} + +```plantuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml +' !include + + +Container(os, "os", "crate", "kernel") +Container(app, "app", "crate", "应用程序") +Container(riscv, "riscv", "crate", "Low level access to RISC-V processors") +Container(lazy_static, "lazy_static", "crate", "A macro for declaring lazily evaluated statics") +Container(rustsbi, "rustsbi", "bin", "") +Container(log, "log", "crate", "日志库") +Container(hart, "hart", "hardware thread", "qemu模拟的硬件线程") + +Rel(os, app, "启动app") +Rel(os, riscv, "操作csr寄存器") +Rel(os, lazy_static, "静态变量初始化") +Rel(os, log, "日志输出") +Rel(os, hart, "trap") +Rel(hart, rustsbi, "中断处理") +Rel(app, hart, "trap") +Rel(hart, os, "中断处理 by trap.S::__alltraps") +``` + +```plantuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml + +Container_Boundary(user, "user", "应用程序"){ + Component(app, "app", "应用程序") + Component(lib, "lib", "", "app入口和库") + Component(console, "console", "", "负责格式化输出") + Component(syscall, "syscall", "", "系统调用") + Component(lang_item, "lang_item", "", "处理panic") +} + +Container(os, "os", "crate", "kernel") +' Container(app, "app", "crate", "应用程序") +Container(riscv, "riscv", "crate", "Low level access to RISC-V processors") +Container(lazy_static, "lazy_static", "crate", "A macro for declaring lazily evaluated statics") +Container(rustsbi, "rustsbi", "bin", "") +Container(log, "log", "crate", "日志库") +Container(hart, "hart", "hardware thread", "qemu模拟的硬件线程") + +Rel(os, lib, "由__restore启动") +Rel(lib, app, "启动main()") +Rel(app, console, "调用println!()") +Rel(console, lib, "调用write()") +Rel(lib, syscall, "调用sys_write(), sys_exit()") +Rel(syscall, hart, "ecall") +Rel(lang_item, console, "当user panic时调用") +Rel(lang_item, lib, "当user panic时调用\n exit()") + +' Rel(os, app, "启动app") +Rel(os, riscv, "操作csr寄存器") +Rel(os, lazy_static, "静态变量初始化") +Rel(os, hart, "ecall") +Rel(os, log, "日志输出") +' Rel(app, hart, "trap") +Rel(hart, rustsbi, "Trap处理") +Rel(hart, os, "Trap处理 by trap.S::__alltraps") + +``` + +```plantuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml +' !include + +Container_Boundary(os, "os", "kernel"){ + Component(main, "os/src/main.rs", "mod", "初始化 Trap处理并加载和执行应用") + Component(lang_items, "os/src/lang_items.rs", "mod", "实现panic_handler") + Component(console, "os/src/console.rs", "mod", "将打印字符的 SBI 接口封装实现格式化输出") + Component(logging, "os/src/logging.rs", "mod", "日志库封装") + Component(sbi, "os/src/sbi.rs", "mod", "封装 sbi") + Component(batch, "os/src/batch.rs", "mod", "user_app批处理") + Component(trap, "os/src/trap/", "mod", "Trap处理") + Component(syscall, "os/src/syscall/", "mod", "系统调用") + Component(sync, "os/src/sync/", "mod", "包装了Refcell,") +} +' Lay_L(console, lang_items) +' Lay_L(lang_items , logging) + + +Container(user, "user", "crate", "应用程序") +Container(rustsbi, "rustsbi", "bin", "") +Container(log, "log", "crate", "日志库") +Container(riscv, "riscv", "crate", "Low level access to RISC-V processors") +Container(lazy_static, "lazy_static", "crate", "A macro for declaring lazily evaluated statics") +Container(hart, "hart", "Hardware Thread", "qemu模拟的硬件线程") + +Rel_D(main, console, "") +Rel_D(main, logging, "init()") +Rel(logging, log, "impl Log") +Rel_L(main, log, "log相关函数") +Rel(main, batch, "init() \n run_next_app()") +Rel(main, trap, "init()") +Rel(trap, console, "") +Rel(trap, riscv, "csr寄存器操作") +Rel(trap, syscall, "处理syscall") +Rel(trap, user, "通过trap.S::__restore\n 启动user") +Rel(batch, sync, "UPSafeCell") +Rel(batch, lazy_static, "延迟初始化user_MANAGER") +BiRel(batch, trap, "run_next_app()\n context相关操作 trap.S::__restore") +Rel(syscall, batch, "run_next_app()") +Rel(console, sbi, "console_putchar()") +Rel(log, console, "") +Rel(sbi, hart, "ecall") +Rel(hart, sbi, "中断处理") +Rel(user, hart, "trap") +Rel(hart, trap, "中断处理\n by trap.S::__alltraps") +Rel(lang_items, console, "发生 os panic 时\n调用println!()") +Rel(lang_items, sbi, "发生 os panic 时\n调用shutdown()") +``` + +```mermaid +zenuml + +title 除第一单元的内容外os的初始化 + +main +trap as "trap/mod.rs" +batch +context as "trap/context.rs" +traps as "trap/trap.S" +riscv as "riscv crate" + +main -> main.clear_bss() +trap.init() { + riscv."stvec:write(__alltraps as usize, TrapMode::Direct)" +} +batch.init() { + print_app_info() { + // 第一次加载APP_MANAGER + "APP_MANAGER.exclusive_access().print_app_info()" { + // 会初始化num_app, current_app, app_start + "UPSafeCell::new" + } + } +} +batch.run_next_app() { + "app_manager.get_current_app()" { + return current_app + } + "app_manager.load_app(current_app)" + "app_manager.current_app += 1" + "drop(app_manager)" + + // 设置sstatus中的spp位为User,
初始化cx{x, status: status, sepc: entry},并设置sp即cx.x[2]为user_stack_top + "context.AppContext.app_init_context(APP_BASE_ADDRESS as entry, USER_STACK.get_sp() as sp,)" { + return ct + } + + // 将cx压入kernal_stack中,并返回kernal_stack_top即cx_ptr + "KERNEL_STACK.push_context()" { + return cx_ptr + } + + // 用cx的内容设置好通用寄存器的字,并用sret返回 + traps.__restore(kernal_stack_top) +} + +``` + +```mermaid +zenuml +title user + +app +lib +console +lib +syscall +panic + +lib.run() { + lib -> lib.clear_bss() +app.main() { + console.println() { + print() { + ConsoleBuffer.write_fmt() { + write_str() { + lib.write() { + syscall.sys_write() { + syscall() + } + } + } + } + } + } +} + +lib -> lib.exit() { + syscall.sys_exit() { + syscall() + } +} + +} + +opt { + panic.panic() { + console.println() { + print() { + ConsoleBuffer.write_fmt() { + write_str() { + lib.write() { + syscall.sys_write() { + syscall() + } + } + } + } + } + } + lib.exit(-1) { + syscall.sys_exit(-1) { + syscall() + } + } + } +} +``` + +```mermaid +zenuml +title 系统调用的过程 + +user_syscall as "user/syscall.rs" +Hart +traps as "os/src/trap/trap.S" +trap as "os/src/trap/mod.rs" +console as "os/src/console.rs" +batch as "os/src/batch.rs" +os_lang_items as "os/src/os_lang_items.rs" +os_syscall as "os/src/syscall/mod.rs" +fs as "os/src/syscall/fs.rs" +process as "os/src/syscall/process.rs" + +user_syscall -> Hart.ecall() { + // 设置sstatus.SPP为 CPU当前的特权级(U/S) + // 设置sepc,scause,stval + "设置trap相关的csr寄存器" + //CPU 会跳转到stvec所设置的Trap 处理入口地址, + //并将当前特权级设置为 S,然后从Trap 处理入口地址处开始执行 + //该位置在os/src/main.rs调用os/src/trap/mod.rs::init()时设置 + //保存几乎所有通用寄存器以及sstatus和sepc + traps.__alltraps { + trap.trap_hander(cx_ptr) { + // 根据 scause 进行匹配 + if ("Exception::UserEnvCall") { + "cx.sepc += 4" + os_syscall."syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]])" { + // 根据 syscall_id 进行匹配 + if (SYSCALL_WRITE) { + fs."sys_write(args[0], args[1] as *const u8, args[2])" { + console.print() + } + } else if (SYSCALL_EXIT) { + process."sys_exit(args[0] as i32)" { + logging."trace!()" + batch.run_next_app() + } + } else { + core."panic!()" + } + } + } else if ("Exception::StoreFault | Exception::StorePageFault") { + console.println() + batch.run_next_app() + } else if ("Exception::IllegalInstruction") { + console.println() + batch.run_next_app() + } else { + core.panic() { + os_lang_items.panic() { + console.println() + sbi."shutdown()" + } + } + } + return cx_ptr + } + __restore + sret + } +} +``` + +### 第三章 + +```plantuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml + +Container(os, "os", "crate", "kernel") +Container(app, "app", "crate", "应用程序") +Container(riscv, "riscv", "crate", "Low level access to RISC-V processors") +Container(lazy_static, "lazy_static", "crate", "A macro for declaring lazily evaluated statics") +Container(rustsbi, "rustsbi", "bin", "") +Container(log, "log", "crate", "日志库") +Container(hart, "hart", "hardware thread", "qemu模拟的硬件线程") + +Rel(os, app, "启动app") +Rel(os, riscv, "操作csr寄存器") +Rel(os, lazy_static, "静态变量初始化") +Rel(os, log, "日志输出") +Rel(os, hart, "trap") +Rel(hart, rustsbi, "中断处理") +Rel(app, hart, "trap") +Rel(hart, os, "中断处理 by trap.S::__alltraps") + +``` + +```plantuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml + +Container_Boundary(os, "os", "kernel"){ + Component(main, "os/src/main.rs", "mod", "初始化 Trap 处理并加载和执行应用") + Component(lang_items, "os/src/lang_items.rs", "mod", "实现 panic_handler") + Component(console, "os/src/console.rs", "mod", "将打印字符的 SBI 接口封装实现格式化输出") + Component(sbi, "os/src/sbi.rs", "mod", "封装 SBI") + Component(trap, "os/src/trap/", "mod", "Trap 处理") + Component(syscall, "os/src/syscall/", "mod", "系统调用") + Component(loader, "os/src/loader.rs", "mod", "将应用加载到内存并进行管理") + Component(sync, "os/src/sync/", "mod", "包装了 RefCell,实现内核内部的可变性") + Component(task, "os/src/task/", "mod", "任务管理") + Component(timer, "os/src/timer.rs", "mod", "RISC-V timer-related functionality") +} + +Container(user, "user", "crate", "应用程序") +Container(rustsbi, "rustsbi", "bin", "SBI 实现") +Container(riscv, "riscv", "crate", "低级别访问 RISC-V 处理器") +Container(lazy_static, "lazy_static", "crate", "延迟初始化的静态变量宏") +Container(hart, "hart", "Hardware Thread", "QEMU 模拟的硬件线程") + +Rel(main, console, "") +Rel(main, trap, "初始化 Trap 处理\n 启用supervisor timer interrupt") +Rel(main, loader, "加载应用到内存") +Rel(main, timer, "Set the next timer interrupt") +Rel(main, task, "初始化任务管理\n并运行第一个任务") +Rel(trap, riscv, "操作 CSR 寄存器") +Rel(trap, syscall, "处理系统调用") +Rel(trap, hart, "通过 trap.S::__restore 启动用户态应用") +Rel(task, sync, "使用 RefCell 包装TaskManager内部的可变部分") +Rel(task, lazy_static, "使用 lazy_static! 定义TASK_MANAGER") +Rel(task, loader, "init_app_cx") +Rel(syscall, console, "处理 sys_write") +Rel(syscall, task, "退出或挂起当前任务,\n并运行下一个") +Rel(syscall, timer, "get_time_us()") +Rel(console, sbi, "使用 console_putchar 通过 SBI 输出字符") +Rel(sbi, hart, "通过 `ecall` 与硬件线程交互") +Rel(user, hart, "用户态应用通过 `ecall` 发起系统调用") +Rel(hart, trap, "处理中断和系统调用,由 trap.S::__alltraps进入") +Rel(hart, rustsbi, "处理 SBI 调用") +Rel(lang_items, console, "发生 OS panic 时调用 println!()") +Rel(lang_items, sbi, "发生 OS panic 时调用 shutdown()") + +``` + +```plantuml +!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml + +Container_Boundary(user, "user", "应用程序"){ + Component(app, "app", "应用程序") + Component(lib, "lib", "", "app入口和库") + Component(console, "console", "", "负责格式化输出") + Component(syscall, "syscall", "", "系统调用") + Component(lang_item, "lang_item", "", "处理panic") +} + +Container(os, "os", "crate", "kernel") +' Container(app, "app", "crate", "应用程序") +Container(riscv, "riscv", "crate", "Low level access to RISC-V processors") +Container(lazy_static, "lazy_static", "crate", "A macro for declaring lazily evaluated statics") +Container(rustsbi, "rustsbi", "bin", "") +Container(log, "log", "crate", "日志库") +Container(hart, "hart", "hardware thread", "qemu模拟的硬件线程") + +Rel(os, lib, "由__restore启动") +Rel(lib, app, "启动main()") +Rel(app, console, "调用println!()") +Rel(console, lib, "调用write()") +Rel(lib, syscall, "调用sys_write(), sys_exit()") +Rel(syscall, hart, "ecall") +Rel(lang_item, console, "当user panic时调用") +Rel(lang_item, lib, "当user panic时调用\n exit()") + +' Rel(os, app, "启动app") +Rel(os, riscv, "操作csr寄存器") +Rel(os, lazy_static, "静态变量初始化") +Rel(os, hart, "ecall") +Rel(os, log, "日志输出") +' Rel(app, hart, "trap") +Rel(hart, rustsbi, "Trap处理") +Rel(hart, os, "Trap处理 by trap.S::__alltraps") + +``` + +```mermaid +zenuml + +title 除第一单元的内容外os的初始化 忽略了log和heap + +main +trap as "trap" +loader as "loader.rs" +riscv as "riscv crate" + +main.run() { + +main -> main.clear_bss() +trap.init() { + riscv."stvec:write(__alltraps as usize, TrapMode::Direct)" +} + +// 将app一次性地依次加载到内存0x80400000处 +loader.init() + +// enable timer interrupt in supervisor mode +trap.enable_timer_interrupt() { + riscv."sie::set_stimer()" +} + +timer.set_next_trigger() { + get_time() { + riscv."register::time::read()" + } + sbi.set_timer() +} + +task.run_first_task() { + "lazy_static初始化TASK_MANAGER" { + for ("i, task") { + // set and get app info with entry and sp and save TrapContext in kernel stack + kernel_stack_top = loader.init_app_cx(i) { + // 设置sstatus中的spp位为User,
初始化cx{x, status: status, sepc: entry},
并设置sp即cx.x[2]为user_stack_top + trap."context.TrapContext.app_init_context( get_base_i(i), USER_STACK[i].get_sp(),)" { + return trap_cx + } + + // 将cx压入kernal_stack中,并返回kernal_stack_top即trap_cx_ptr + "KERNEL_STACK[i].push_context(cx)" { + return trap_cx_ptr + } + } + + // Create a new task context with a trap return addr and a kernel stack pointer + "task.task_cx = TaskContext::goto_restore(trap_cx_ptr)" + "task.task_status = TaskStatus::Ready" + } + return TASK_MANAGER + } + // 第一次使用TASK_MANAGER时,会初始化TASK_MANAGER + "TASK_MANAGER.run_first_task()" { + "task0.task_status = TaskStatus::Running" + // 启动第一个应用不是在内核栈中
该栈sp会被丢弃,不会再返回了 + "__switch(&mut _unused as *mut TaskContext, next_task_cx_ptr)" { + // 注意在__switch中已将sp设为内核栈顶
启动第一个应用不是在内核栈中
该栈sp会被丢弃,不会再返回了 + trap."trap.S::__restore" + } + } +} + +} +``` + +```mermaid +zenuml +title 系统调用的过程 + +user_syscall as "user/syscall.rs" +Hart +traps as "trap/trap.S" +trap as "trap/mod.rs" +console as "/console.rs" +batch as "batch.rs" +os_lang_items as "os_lang_items.rs" +os_syscall as "syscall/mod.rs" +fs as "syscall/fs.rs" +process as "syscall/process.rs" +task as "task" +timer as "timer.rs" + +user_syscall -> Hart.ecall() { + // 设置sstatus.SPP为 CPU当前的特权级(U/S) + // 设置sepc,scause,stval + "设置trap相关的csr寄存器" + // CPU 会跳转到stvec所设置的Trap 处理入口地址 + // 并将当前特权级设置为 S,然后从Trap 处理入口地址处开始执行 + // 该位置在os/src/main.rs调用os/src/trap/mod.rs::init()时设置 + // 保存几乎所有通用寄存器以及sstatus和sepc + traps.__alltraps { + trap.trap_hander(cx_ptr) { + // 根据 scause 进行匹配 + if ("Exception::UserEnvCall") { + "cx.sepc += 4" + os_syscall."syscall(cx.x[17], [cx.x[10], cx.x[11], cx.x[12]])" { + // 根据 syscall_id 进行匹配 + if (SYSCALL_WRITE) { + fs."sys_write(args[0], args[1] as *const u8, args[2])" { + console.print() + } + } else if (SYSCALL_EXIT) { + process."sys_exit(args[0] as i32)" { + logging."trace!()" + task.exit_current_and_run_next() { + mark_current_suspended() + run_next_task() { + // 从TASK_MANAGER中取出下一个任务 + // 将其状态设置为Running + // 更新TASK_MANAGER中的当前任务为下一个任务 + // 通过__switch启动下一个任务 + __switch(current_task_cx_ptr, next_task_cx_ptr) { + if ("要启动的app是初次启动") { + "保存current_app的Trap控制流" + // 其实是创建一个新的TrapContext
准备好在__restore中启动app的前置条件 + "恢复next_app的Trap控制流" + // 不能在他人的内核栈中运行,
应直接跳到__restore启动app + traps.__restore + } else { + "保存current_app的Trap控制流" + // 仿佛是next_app正常trap然后返回 + // 在返回后,在进入__restore + "恢复next_app的Trap控制流" + return + } + } + } + } + } + } else if (SYSCALL_YIELD) { + sys_yield() { + logging."trace!()" + task.suspend_current_and_run_next() { + mark_current_suspended() + run_next_task() + } + } + } else if (SYSCALL_GET_TIME) { + "sys_get_time(args[0] as *mut TimeVal, args[1])", + } else { + core."panic!()" + } + } + } else if ("Exception::StoreFault | Exception::StorePageFault") { + console.println() + task.exit_current_and_run_next() { + mark_current_suspended() + run_next_task() + } + } else if ("Exception::IllegalInstruction") { + console.println() + task.exit_current_and_run_next() + } else if ("Trap::Interrupt(Interrupt::SupervisorTimer)") { + timer.set_next_trigger() + task.suspend_current_and_run_next() { + mark_current_suspended() + run_next_task() + } + } else { + core.panic() { + os_lang_items.panic() { + console.println() + sbi."shutdown()" + } + } + } + return cx_ptr + } + __restore() + sret + } +} +``` + +```mermaid +zenuml +title user + +app +lib +console +lib +syscall +panic + +lib.run() { + lib -> lib.clear_bss() +app.main() { + console.println() { + print() { + ConsoleBuffer.write_fmt() { + write_str() { + lib.write() { + syscall.sys_write() { + syscall() + } + } + } + } + } + } +} + +lib -> lib.exit() { + syscall.sys_exit() { + syscall() + } +} + +} + +opt { + panic.panic() { + console.println() { + print() { + ConsoleBuffer.write_fmt() { + write_str() { + lib.write() { + syscall.sys_write() { + syscall() + } + } + } + } + } + } + lib.exit(-1) { + syscall.sys_exit(-1) { + syscall() + } + } + } +} +``` + +### 第四章 + +```plantuml +package mm { + +class address { +} + +struct PhysAddr { + +0: usize + +floor() -> PhysPageNum + +ceil() -> PhysPageNum + +page_offset() -> usize + +aligned() -> bool + +get_mut() -> &'static mut T +} + +struct VirtAddr { + +0: usize + +floor() -> VirtPageNum + +ceil() -> VirtPageNum + +page_offset() -> usize + +aligned() -> bool +} + +struct PhysPageNum { + +0: usize + +get_pte_array() -> &'static mut [PageTableEntry] + +get_bytes_array() -> &'static mut [u8] + +get_mut() -> &'static mut T +} + +struct VirtPageNum { + +0: usize + +indexes() -> [usize; 3] +} + +struct SimpleRange { + l: T + r: T + +new(start: T, end: T) -> Self + +get_start() -> T + +get_end() -> T +} + +struct SimpleRangeIterator { + current: T + end: T + +new(l: T, r: T) -> Self + +next() -> Option +} + +class StepByOne { + +step() +} + +address o-- PhysAddr : 定义 +address o-- VirtAddr : 定义 +address o-- PhysPageNum : 定义 +address o-- VirtPageNum : 定义 +address o-- SimpleRange : 定义 +address o-- SimpleRangeIterator : 定义 +address *-- StepByOne : 实现 + +PhysAddr *-- PhysPageNum +VirtAddr *-- VirtPageNum +SimpleRange *-- SimpleRangeIterator : 迭代器 + +class frame_allocator { + init_frame_allocator() + frame_alloc() -> Option + frame_dealloc(ppn: PhysPageNum) +} + +struct FrameTracker { + +ppn: PhysPageNum + +new(ppn: PhysPageNum) -> Self +} + +struct StackFrameAllocator { + current: usize + end: usize + recycled: Vec + +new() -> Self + +init(l: PhysPageNum, r: PhysPageNum) + +alloc() -> Option + +dealloc(ppn: PhysPageNum) +} + +class FrameAllocator { + +new() -> Self + +alloc() -> Option + +dealloc(ppn: PhysPageNum) +} + +frame_allocator o-- FrameTracker : 定义 +frame_allocator o-- StackFrameAllocator : 定义 +frame_allocator *-- FrameAllocator : 实现 + +StackFrameAllocator *-- FrameAllocator : 实现 + +class heap_allocator { + init_heap() + heap_test() +} + +heap_allocator o-- LockedHeap : 使用 + +class memory_set { + kernel_stack_position(app_id: usize) -> (usize, usize) + remap_test() +} + +struct MemorySet { + page_table: PageTable + areas: Vec + +new_bare() -> Self + +token() -> usize + +insert_framed_area(...) + +push(...) + +map_trampoline() + +new_kernel() -> Self + +from_elf(elf_data: &[u8]) -> (Self, usize, usize) + +activate() + +translate(vpn: VirtPageNum) -> Option + +shrink_to(...) + +append_to(...) +} + +struct MapArea { + vpn_range: VPNRange + data_frames: BTreeMap + map_type: MapType + map_perm: MapPermission + +new(...) + +map_one(...) + +unmap_one(...) + +map(page_table: &mut PageTable) + +unmap(page_table: &mut PageTable) + +shrink_to(...) + +append_to(...) + +copy_data(...) +} + +enum MapType { + Identical + Framed +} + +class MapPermission { + +R + +W + +X + +U +} + +memory_set o-- MemorySet : 定义 +memory_set o-- MapArea : 定义 +memory_set o-- MapType : 定义 +memory_set o-- MapPermission : 定义 + + +class page_table { + translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&'static mut [u8]> +} + +class PTEFlags { + +V + +R + +W + +X + +U + +G + +A + +D +} + +struct PageTableEntry { + +bits: usize + +new(ppn: PhysPageNum, flags: PTEFlags) -> Self + +empty() -> Self + +ppn() -> PhysPageNum + +flags() -> PTEFlags + +is_valid() -> bool + +readable() -> bool + +writable() -> bool + +executable() -> bool +} + +struct PageTable { + root_ppn: PhysPageNum + frames: Vec + +new() -> Self + +from_token(satp: usize) -> Self + +find_pte_create(...) + +find_pte(...) + +map(vpn: VirtPageNum, ppn: PhysPageNum, flags: PTEFlags) + +unmap(vpn: VirtPageNum) + +translate(vpn: VirtPageNum) -> Option + +token() -> usize +} + +page_table o-- PTEFlags : 定义 +page_table o-- PageTableEntry : 定义 +page_table o-- PageTable : 定义 + +PageTable *-- PageTableEntry +PageTableEntry *-- PTEFlags +PageTable *-- FrameTracker + + +MemorySet *-- PageTable +MemorySet *-- MapArea +MapArea *-- VPNRange +MapArea *-- FrameTracker +MapArea *-- MapType +MapArea *-- MapPermission +} +``` + +```mermaid +zenuml + + +page_table +address +frame_allocator + +// Find PageTableEntry by VirtPageNum, create a frame for a 4KB page table if not exist +page_table."find_pte_create(&mut self, vpn: VirtPageNum)" { + // Get the indexes of the page table entry + address."VirtPageNum::indexes(&self)" { + return "idxs: [usize; 3]" + } + + for ("(i, idx) in idxs") { + // Get the reference of page table(array of ptes) + address."PhysPageNum::get_pte_array(&self)" { + return "&'static mut [PageTableEntry]" + } + + if(i == 2) { + return "Some(pte)" + } + + // The page pointered by page table entry is valid? + bool valid = "PageTableEntry::is_valid(&self)" + + if(!valid) { + // Allocate a physical page frame in FrameTracker style + frame_allocator.frame_alloc() { + + "FRAME_ALLOCATOR.exclusive_access().alloc()" { + return "Option" + } + + // Create a new FrameTracker
+ // clean page + "Option::map(FrameTracker::new)" { + return "Option" + } + + return "Option" + } + + "*pte = PageTableEntry::new(frame.ppn, PTEFlags::V);" + "self.frames.push(frame);" + } + + } +} +``` diff --git "a/source/_posts/2024\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223/2_unit_\345\206\205\345\255\230\345\270\203\345\261\200\345\233\276.svg" "b/source/_posts/2024\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223/2_unit_\345\206\205\345\255\230\345\270\203\345\261\200\345\233\276.svg" new file mode 100644 index 00000000000..ddd98722b58 --- /dev/null +++ "b/source/_posts/2024\344\272\214\351\230\266\346\256\265\346\200\273\347\273\223/2_unit_\345\206\205\345\255\230\345\270\203\345\261\200\345\233\276.svg" @@ -0,0 +1 @@ +0x1000qemu初始化代码0x8000 0000rustsbi-qemu.bin代码os代码.text.rodate.date.bss.stack.bssos code多个app code0x8020 0000kernal stackuser stack app code 单个app code_startos stack0x 8040 0000entry.asmrust_mainapp_manager.load_app(current_app)goto \ No newline at end of file From c67312febb57ddc4265b2b7f317bf5fc6809d032 Mon Sep 17 00:00:00 2001 From: xingmin1 Date: Sun, 1 Dec 2024 22:31:35 +0800 Subject: [PATCH 2/2] =?UTF-8?q?add=202024=E7=A7=8B=E5=86=AC=E5=AD=A3?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E4=B8=89=E6=80=BB=E7=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...66\346\256\265\346\200\273\347\273\223.md" | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 "source/_posts/2024\344\270\211\351\230\266\346\256\265\346\200\273\347\273\223.md" diff --git "a/source/_posts/2024\344\270\211\351\230\266\346\256\265\346\200\273\347\273\223.md" "b/source/_posts/2024\344\270\211\351\230\266\346\256\265\346\200\273\347\273\223.md" new file mode 100644 index 00000000000..f99fb8ecc94 --- /dev/null +++ "b/source/_posts/2024\344\270\211\351\230\266\346\256\265\346\200\273\347\273\223.md" @@ -0,0 +1,56 @@ +--- +title: 2024三阶段总结 +date: 2024-12-01 17:47:45 +tags: +--- + +# 2024三阶段总结 + +由于考试和双十一的影响,导致我实际学习三阶段的时间不到一周,到目前为止,勉强把实验做完了(除了最后一个套娃arceos的实验还没有看)。考试自不必多说,至于双十一嘛,是由于外存不够了,要升级一下,然后迁移系统、配置环境什么的。 + +由于时间较少,而且刚考完一场试,变懒了,所以对ArceOS还没有仔细研究,下面的内容可能较空泛、可能有错误。 + +## Unikernel +在我看来,Unikernel是一个与业务无关的裸机应用,分层、模块化且可扩展,根据业务的需要可以选取需要模块或对模块进行扩展,可以像正常开发linux c应用或std rust应用一样迅速开发裸机应用。 + +在这一阶段,被迫看了一些关于feature、attribute、条件编译的一些知识,头一次知道原来rust里面还有workspace。 + +>- print_with_color +> +>就加一些特殊的字符 + +>- support_hashmap +> +>看群内大佬讨论,就引了一个库 + +>- alt_alloc +> +> 对于这个,一开始还想最初的页是怎么分配来的,后来才想明白这些页已经固定下来了,只要考虑怎么管理就行了。 + +>- shell +> +> 对于mv操作,我一开始想的是仅移动指向inode的指针,不拷贝文件,但发现实现有些难,就没有这样做。最终rename和mv都用了rename实现,感觉有些奇怪,但起码测例能过,不愧是arceOS,就是通用。 + +## 宏内核 +如果按照上面的理解的话,宏内核是Unikernel上的应用,但是又有些不太对,相比于实现业务目的,它更倾向于是扩展Unikernel,看起来有些像“内核之上不只有应用,还有内核的微内核”。 + +>- page_fault +> +> 相比于实现page_fault,我更关注的是linkme这种骚操作。 + +>- sys_map +> +> 就find_free_area然后read进去,虽然感觉用find_free_area找到的地方有些不符合man mmap的说明。 + +## Hypervisor +在三阶段的实现中,看起来Hypervisor最没用,在裸机之上实现裸机,大部分实现都是透传的,相比于直接运行在裸机上,不仅功能减少了、性能变差了,就连能源的使用也不只是烧电,还烧头发,悲。 + +还有,感觉可不可以在ArceOS上同时运行宏内核或其他应用和Hypervisor,ASA(ArceOS Subsystem for ArceOS)1.0就在眼前 + +>- simple_hv +> +> 改一下guest的sepc,设置一下a0、a1的值 + +>- pflash设备模拟方式 +> +> 一开始没有搞清gpa映射到hpa时,没有经过host的satp,导致在host中拿着pa当va来用,出现了问题。另外,在完成后,修改了一下pflash的内容,想要读u128转string输出,但是没想到,在对* u128解引用时,它居然会先读u128的高64位,导致映射时页面没对齐。 \ No newline at end of file