0%

目录

  1. 第一阶段:Rust编程学习
  2. 第二阶段:rCore 操作系统学习
  3. 第三阶段:ArceOS 代码阅读与实践
  4. 总结与收获

第一阶段:Rust编程学习

感想

第一阶段主要是学习 Rust 语言。Rust 拥有完善的官方文档和丰富的社区资源。
我通过完成 rustlings 练习来熟悉语法和常用特性,遇到不懂的地方就查阅官方手册和社区博客。
这一阶段让我对 Rust 的所有权、借用、生命周期等核心概念有了更深入的理解。

第二阶段:rCore 操作系统学习

感想

第二阶段聚焦于 rCore 操作系统的学习。rCore 项目内容丰富,涵盖了操作系统的各个核心模块。
我花了大约两周时间,逐章阅读并动手实践,过程中遇到不少挑战,但也极大提升了我的系统编程能力。
通过查阅 RISC-V 参考手册和相关资料,逐步理清了内核启动、进程管理、内存管理等知识点。

第三阶段:ArceOS 代码阅读与实践

感想

第三阶段主要是阅读 ArceOS 的源码并尝试参与部分模块的开发。
与 rCore 相比,ArceOS 的架构更加模块化和易于扩展。
虽然刚开始阅读时有些吃力,但通过不断调试和查阅文档,逐渐理解了其设计思路和实现细节。
这一阶段锻炼了我的代码阅读能力和团队协作能力。

总结与收获

通过本次训练营,我不仅系统学习了 Rust 语言和操作系统原理,还提升了独立解决问题和查阅资料的能力。
同时也暴露了自己在算法和底层实现方面的不足,后续会继续加强相关训练。
感谢 rcore-os 社区和各位导师的指导!

参考资料

  1. rCore 项目文档
  2. Rust 官方文档
  3. RISC-V 参考手册

基础阶段 - Rust编程

第一阶段是 Rust 编程,让我印象深刻的是 rustling 中链表的习题,那一刻我深深地怀疑为什么要使用 Rust,在之后的阶段中也多次因为对 Rust 语法的不熟悉而头脑混乱,所以在基础阶段确实要好好利用时间认真地学习 Rust 基础,我现在都还在在过 Rust 圣经…

专业阶段 - OS设计实现

这一阶段就开始对 OS 部分进行学习,二阶段我觉得整个文档都写得非常清晰,整个学习中虽然实验是从第三章开始的,但是或许是因为我之前只是看了操作系统导论,实际上我在第一章节和第二章节的学习上花费了更多的时间,我觉得这个视角就开始切换了,从一开始写应用程序我们进行系统调用和到开发内核的视角,链接脚本,汇编语言,SBI 等等,我觉得理解内核的执行环境也是一个很重要的点

第三章 是对应特权级切换的,学习特权级切换的硬件控制机制,初始化 Trap 处理点 __alltraps() , trap_handler() 实现 Trap 的分发和处理,到 __restroe() 对 Trap 上下文切换的恢复,很有意思的一章

  • lab 3: 简单的使用一个数组记录每一个系统调用的次数,比较要注意的是,这里是分时系统,不同程序的系统调用次数要隔离开,一开始我实现的是在每一次加载新的任务的时候对系统调用次数进行重置,但那是在批处理的情况下,批处理是一个一个任务进行的,但是 lab 3 是分时系统,所以存放的位置应该是和任务有关系的.

第四章 是对应地址空间,这里我觉得主要讲解了

  1. 在分页机制下,为什么要将 Trap 上下文保存在应用地址空间而不是将其直接放在应用的内核栈,对应理解跳板

  2. 然后就是对 __alltraps 和 __restore 下是如何保存和恢复 Tarp 上下文时切换地址地址空间的代码部分的修改

  3. 然后就是系统调用后,用户传的地址不要直接解用户地址访问,那是用户空间的虚拟地址

    • lab 4: 主要就是地址空间的转换,对系统调用,如果用户传的是指针的话,都要通过手动查表的方式将地址映射成为内核可以访问的地址, 对 mmap 和 munmap 映射部分,在实现 munmap 过程中,有遇见一个问题,在检查 munmap 是否可以 unmap 的时候,必须要保证每个页都是被 map 过的,并且需要是同一个 MapArea,不然如果分开来,可能会说可能其他逻辑段映射了,但是不是同一个逻辑段,这样是不对的,然后不要忘记在进行 map 的时候要补上 Valid 标志 !

第五章 是进程相关的,内核栈,进程控制块,任务管理器,处理器,进程的调度机制

  • lab 5: 内部首先通过 get_app_data_by_name 获得对应 app 的 elf_data, 然后创建对应的 task_control_block, 要注意的是,一开始直接使用 new() 方法,但 new() 只有在创建初始进程的时候才可以,对应的实现从 fork 和 new,exec 方法中可以借鉴,同样要维护对应的父子关系

第六章 文件系统

  • lab 6: 这里也是有一个问题,就是引入文件系统后,测试就是之前的测试没有过,在群中找才知道 sprawn 要对对应的标准输出输入和错误的文件描述符进行初始化,所以真的,积极地交流是很重要的,虽然我确实太菜了,很多时候连问题都提不出来,,,不过这也算是一个努力的点吧,都只能一点一点来

第八章 内核态操作系统方法实现锁

  • lab 8: 完成死锁检测,主要是对 need 的维护,再检测到安全之后,need 不能直接就恢复,这个恢复need的话,那有可能检测不出来啊,比如说线程1获得1,线程2获得2,然后线程一想要获得2,他去进行检测,然后他不会检测到有问题啊,因为这个时候线程2的need他会以为是0,好他就会认为2会释放啊,然后线程一就会得到这次的sem_down的允许,然后之后线程2想要获得1,如果说线程一的need就恢复了,线程2也会以为线程1是可以释放的,因为此时线程一的need被恢复了,就是原本的0,然后线程2这次的也被允许了,那就死锁了呗
  • 然后在对应的 sem_deadlock_2.rs 中,对应的 semaphore.up, 这里的,不能直接就只是 available + 1, 然后对应的 allocation - 1,这样是不可以的,程序会检测到死锁,但实际上没有死锁,在检测的时候,要先看是否是 need,如果有 need 就只是对 need 进行修改,而不是直接改 available 和 allocation,但是理解为什么还比较模糊

项目基础阶段 - 组件化操作系统

在这里我比较印象深刻是文件系统这一部分的实现,一开始我执行 shell 是觉得这部分测试是可以的,在最后提交的时候才发现原来我竟然是使用的标准库的而没有使用 axstd,然后之后再去实现 armf 中的 rename 方法,在同一个文件夹下 rename 的逻辑,而没有 move 的实现逻辑,但是测试的时候依然报错,而且利用输出给我的感觉是整个代码 都没有运行到我的 axfs_ramfs中,实在想不出原因在角落群中才看见 ”rename实现为了启用本地的 axfs_ramfs要在根目录下的 patch 添加本地的 ramfs“,感谢,,,以及被自己蠢哭。。。不过在这个过程中也是算是对整个文件结构有了一定的了解,是一种组件化的感觉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
rceos
.
├── api
│   ├── arceos_api
│   ├── arceos_posix_api
│   └── axfeat
├── axfs_ramfs
│   ├── Cargo.toml
│   ├── Cargo.toml.orig
│   ├── README.md
│   └── src
├── modules
│   ├── alt_axalloc
│   ├── axalloc
│   ├── axconfig
│   ├── axdisplay
│   ├── axdma
│   ├── axdriver
│   ├── axfs
│   ├── axhal
│   ├── axlog
│   ├── axmm
│   ├── axnet
│   ├── axruntime
│   ├── axsync
│   ├── axtask
│   ├── bump_allocator
│   ├── elf
│   └── riscv_vcpu
├── ulib
│   ├── axlibc
│   └── axstd

总结

恩,其实诚实地说虽然做了实验,但是现在其实还是有一种脑袋空空的感觉,当然我觉得肯定是对这个有更直观的理解了,然后在知识上我觉得自己没有什么要说的,我觉得整个文档写得很好第三阶段石磊老师的课讲得也非常好,而且因为其实本身可能自己的吸收还是没有很系统,确实能力有限,就给一些我自己学习过程的建议吧

首先实验的完成部分很多都是借鉴相关的部分,我觉得在实验上就是要多看相关的代码,然后不断借鉴,也不要怕错,就只有胆大心细

然后就是在看文档知识的时候我比较推荐就是把它拆出来的感觉,然后放在一个类似 excalidraw 或者 draw.io 的看板上,也可以自己写一些批注,我也尝试就是写博客那种但是一整块流下来的感觉怎么说我自己就是看着很累,但是使用化肥然后拆出来我个人感觉是比较顺畅的,也经常在遇见问题之后没有想法的时候,就到处翻翻,或许就能找到答案,而且画图的这种给的笔记压力也比较小一些,但是不得不说在后面内容多之后确实会有点乱,这种情况下我觉得就是需要再梳理的,可能以另外一个形式或者是什么的,但是我觉得这样拆出来之后就算是复习我个人感觉会比较流畅,不会有太大的压力

两种方式的对比
这是我尝试的两种方法对比,左边是那种拆出来的,右边就是纯文字的博客,我个人是看左边更觉得看得下去一点…

笔记截图
然后这是我的一个粗略的笔记截图,我就是在这个图上找来找去看一下可能有关联的点…

这种方法是我自己学习下来觉得对我帮助比较大的,然后在之后的复习中没有给我太大压力的感觉,当然我认为每个人适合的方式是不同的,这也只是我自己的感受而已,反正客观地看吧

完结撒花

总结

有了第二阶段的基础,第三阶段相对更好理解了,有些第二阶段有点模糊的在第三阶段也更清晰了,第三阶段作业相比第二阶段更简单。

  • ex1 print_with_color: 2025.05.06
    先是axhal中修改了,没处理好换行符,导致后面的练习通不过,后换成在ulib里修改
  • ex2 hashmap 2025.05.07: 主要参考std中的hashmap
  • ex3 bump allocator 2025.05.09: 参考了现有的allocator中的写法,key points:1.四个位置指针,2. allocate时的alignment处理和overlap检查, 3.由于是连续的分配,目前不支持dealloc,足以通过ci了
  • ex4 sys_mmap 2025.05.13:找空闲区域,映射找到的区域到新分配的物理内存,加载文件内容到映射好的地址。
  • ex5 ramfs_rename 2025.05.14:最刚开始按slides中的完成的是examples/shell,是fatfs, 5.14补做这个ramfs练习
  • ex6 simple-hv 2025.05.16: 主要理解指令引发异常后, 会调用_guest_exit, 是通过设置stvec设置trap处理入口地址为_guest_exit , _guest_exit执行完成后就返回到_run_guest的返回地址,执行一下条指令,即vmexit_handler

第一阶段

  • 为什么来这个训练营

    • 最初是在寻找 Rust 的练手项目过程中,偶然了解到本训练营。自己本就对系统级编程充满兴趣,因此毫不犹豫地报名参加。
  • 官方通过要求:

    • rustlings+10道算法题
  • 主要参考资料:

  • 学习过程

    • 基于一定的编程基础,我通读了一本 Rust 入门教材,同时刷了约 100 道 LeetCode 算法题,作为语言练习。尤其链表类题目虽然困难,但反而非常适合加深对 Rust 所有权模型的理解。
  • 感想

    • 第一次参与开源社区形式的学习训练营,整体学习路线、资料与交流氛围都非常优质。opencamp 社区内容丰富、质量上乘,是一次令人愉快的学习体验。后续还会继续参与类似项目。

第二阶段

  • 官方通过要求

    • rCore-Camp-Guide-2025S 文档(通过要求)的课后练习
  • 参考资料

    • CSAPP
      • 重点补充:第 7 章 链接过程
    • 操作系统导论
      • 快速回顾前 19 章内容
    • RISV手册
      • 重点理解:解特权级切换
    • rCore-Tutorial-Book-v3 3.6.0-alpha.1 文档(核心)
    • rCore-Camp-Guide-2025S 文档(通过要求)
  • 学习过程

    • 这一阶段持续了约一个月,重点围绕 rCore-Tutorial 详读源码与注释。课后题本身难度不大,但深入理解 rCore 的执行过程与实现细节则颇具挑战。计划后续通过整理文档、写文章的方式进一步复习与巩固。
  • 感想

    • 从“移除应用执行环境支持”出发,到手动链接最简调度系统、构建时间片轮转机制、物理内存页帧管理与多级页表,再到文件系统、线程管理与用户态支持……整个过程让我系统性理解了操作系统的核心构件。以往只是停留在八股文式的“理解层面”,这次才真正从源码出发理解了“为什么这样设计”,并洞察背后的一致性原则与设计哲学。现代软件系统中常见的“新框架”“新技术”,本质上很多都是对底层原理的重新组合与包装。打牢这些底层基础,将对未来应对复杂系统设计提供极大帮助。第二阶段的 rCore 项目就是一个极佳的底层能力训练平台。

第三阶段

  • 官方通过要求
    • 6道练习题,一道挑战题
  • 参考资料
  • 学习过程
    • 得益于第二阶段的深入积累,第三阶段在约三周内顺利完成任务。以文档为主导,同时配合源码阅读与实验。
  • 感想
    • 这一阶段让我初步建立了对“组件化操作系统设计”的理解。ArceOS 的设计将 Rust、OS 内核抽象与组件化思想结合在一起,是极具前沿性的操作系统实践。ArceOS 所体现的“组件化操作系统设计”核心在于:如何在保障各模块职责边界清晰的同时,实现高度解耦却协同有序的组合机制。看似简单,但背后依赖于扎实的底层系统知识与成熟的架构设计思想。ArceOS 不仅是对底层操作系统设计理念的前沿探索,更启发我思考如何在不同工程场景中抽象、迁移并落地组件化设计思想。

      前三阶段总结

    • 总之,确实学到了很多,希望能完成四阶段,最后衷心感谢所有无私奉献的导师和伙伴

      第四阶段

      背景

      我是 Java 后端开发工程师,长期对系统级编程和基础设施方向怀有浓厚兴趣。训练营前,我的目标是借助项目实践机会积累 Rust 经验,并逐步转向系统软件方向。这是我第一次参与开源项目协作,过程中不仅大幅拓宽了技术视野,更激发了我对开源文化的认同与热情,同时促使我对系统级编程领域有了更深入的理解和思考。这些经历坚定了投身系统软件和开源生态建设的决心。

      主要工作

      第一周

  • 梳理了 Rust 中 async/await 异步模型的执行机制和运行时结构
  • 观看向勇老师异步操作系统相关视频,了解异步的操作系统的方向的最近进展
  • 周会上确定了初步目标:使用异步优化smoltcp和Arceos中的网络相关模块

    第二周

  • 完成对 lazyinit 项目的 PR 改进
    • 虽然修改不复杂,但作为第一个开源贡献,对个人具有重要意义
    • 通过深入研究 lazy_staticOnceCell 等标准库机制,加深了对线程安全延迟初始化(全局单例)设计模式的理解
    • 启发我开始构建长期维护项目:Rust 中设计模式最佳实践
  • 完成用户态爬虫
    • 使用 reqwest + tokio 构建异步爬虫,显著感受到异步模型对 I/O 密集型任务的性能提升
    • 通过日志分析发现:爬取网页耗时远超解析网页,确认异步模型对于高并发爬虫的价值
    • 对比 Java 传统线程池 + 回调模型,以及对Rust 异步运行时中future的可组合性,感受到了Rust异步的强大
  • 通过迭代 WebServer 逐步深入 Rust 异步编程
    • 手动实现 pollFuture 等底层机制,结合项目实践理解 async 底层原理
  • 修改目标:
    • 初步阅读 smoltcp 和 ArceOS 的网络模块源码及相关分析文档后,意识到其中涉及的协议细节远超自己的当前掌握程度,一度感到无从下手
    • 正当我陷入焦虑和困惑时,向勇老师的一句,“你要沉下去”给了我极大的启发和鼓励,在老师的建议下,我及时调整目标:从零实现一个简化版的 TCP 协议栈,再逐步尝试贡献到 smoltcp 或 ArceOS 等成熟开源项目中

      第三周

  • 完成 TCB 状态管理结构与部分状态机逻辑
  • 实现服务器的三次握手(SYN)和四次挥手(FIN)流程,具备最基本的连接生命周期管理能力
  • 分支 dev 上尝试更接近 std 的接口模型,目前仍在调试阶段
  • 实现过程中大量阅读 TCP 协议细节、状态转换标准,提升对 TCP/IP 协议的系统理解
  • 项目地址

    总结

    这段训练营经历极大拓宽了我的认知。群里众多优秀开发者让我真正体会到“卓越工程师”的含义:深入技术细节、追求极致设计、乐于分享交流。看着大家在短短一个月内完成高质量、复杂度极高的系统项目,我不仅深受启发、倍感鼓舞,更由衷地感到惊讶。大家对系统设计和实现的理解深度,以及在极短周期内高效推进项目的能力,都远超出了我的预期。这种冲击让我意识到,自己在技术深度以及工程实践上的积累还远远不够,也更加坚定了我沉下心来扎实学习、长期投入开源的决心。
    通过本次训练营,我从 Java 后端开发者的视角,初步窥见了 Rust 在系统编程与异步操作系统方向的技术魅力。并亲手完成了一些系统方向的实践项目,切身感受到开源协作的高效与活力。训练营结束后,我也正式开始计划长期参与开源项目,为社区持续贡献力量。

    下一步目标

  • 长期维护开源项目:
    • design-patterns-rust: 系统收集和实现 Rust 中常见设计模式
    • learn-rust: 构建学习路径、记录 Rust 编程与系统知识
  • 协议栈方向:
    • 持续迭代 tcp-rust 项目,支持更多 TCP 功能(重传、窗口、拥塞控制)
    • 尝试加入异步 API 封装
    • 最终能向 smoltcp / Arceos 提交网络组件相关的 PR

      其他

  • 本次经历的笔记和记录均可在2025春夏季开源操作系统训练营中找到

总结

第一阶段

通过rustlings学习感觉非常有趣,感觉自己在做闯关游戏,每做完一题都非常有成就感,不知不觉就做完了,系统性的学习了rust的语法,不得不说rust写链表是真麻烦啊。

第二阶段

之前参加过一次,但是那时候还没学习操作系统,做起来十分艰难,只把第一个任务做完就放弃了。这次学习的时候虽然已经学习过操作系统了,但是还是感觉恨难,因为要实现功能前要先读懂已有的代码,了解相应数据结构和API,这就花了大量时间,好在磕磕绊绊也是做完了,不过做的确实太慢了,第三阶段已经开始一段时间了。

第三阶段

这个阶段感觉最大的问题是参考文档是个半成品,到了文件系统就没有了,导致我在做ramfs_rename时,一直搞不明白为什么总是提示没有实现,后来才发现代码调用的是crate.io上的ax_ramfs,其中的reanme没有实现,需要在cargo.toml配置patch才行,这里就卡了我很长时间,好在最后全部做完了。

oscamp2025-blog

这是一个记录 2025 Spring Camp 的 repo

本仓库将存储相关实验报告与每日blog

第一阶段:rustlings

4.1

部署了rustlings练习环境,找到了资料并完成了第一节课的练习

4.2

参考官方的 rust book 学习了所有权、struct,并完成相关练习

4.3

学习了mod

4.4-4.6

无进度

4.7

学习了HashMap,Vec,String等容器

4.8

狂补进度,学泛型,trait,有cpp基础就挺好理解的了

4.9

做算法,完成最后10题(其实好像不是算法只是data structure实现)

第二阶段:rcore-tutorial

4.10

配置实验环境,阅读了教程第一章,初步了解了kernel启动需要的过程

4.11

无进度

4.12

阅读教程第二章,了解了用户特权级与内核特权级的切换过程

4.13

阅读第三章,完成lab1和作业1(作业1让我复习了第二章并更深入理解了trap的上下文切换,所以建议保持有分析代码的作业

4.14

无进度

4.15

阅读第四章,完成了lab2的trace部分,

mmap,unmap思路:tcb中保存了每个task的memory set,使用memory set进行alloc即可,预计为接下来的工作
用frame_alloc调了一下午+一晚上…

4.16

预感到数模没时间看os,所以今天赶完了lab2 感觉差不多 以后多用gpt吧

4.17-4.19

无进度

4.20

阅读第五章,了解了进程调度的大致流程

4.21

完成lab3和ch5作业,了解了stride调度的大致的具体实现流程

5.1

要准备期末了,预计要鸽

5.2

完成ch6,7,8

第三阶段 5.3-5.9

练习

1.在axhal中加入ANSI控制字符(后来好像会莫名其妙导致其他测例的评测问题所以更改到user app 了)
2.在axstd中加入hashbrown的hashmap。

练习

alt alloc 模拟实现即可
shell 加了rename和mv 目前是分开写的实现 也就是说mv是独立写的

练习

添加mmap的syscall
先获取fd,然后alloc内存,然后写内容

练习

ramfs_rename ramfs默认不支持rename,在这里要实现的话创建新文件写入然后删除原文件即可
simple_hv 跟cpu设计差不多,回到Guest之后PC+4

5.9 第三阶段完成

从2024年10月开始,我在郭老师和陈老师的指导下开始系统学习 Rust 操作系统,到目前为止已有半年时间,现总结如下。

学习过程

学习主要分为 3 个阶段:Rust 语言学习阶段,操作系统训练营阶段和 Starry 实践阶段。

Rust 语言学习阶段

2024年10月-11月,我参加了 Rust 学习赛。在此之前我对 Rust 的了解仅限于一些最基本的语法,没有用 Rust 写代码的经历。这次比赛于我而言是以赛促学,直接投入实践。我先是通过看训练营的课件和网上的一些资料,完成 rustlings 的练习,初步熟悉了 Rust 的语法和一些基本概念。然后参加比赛。初赛相对简单,只需要完成一些相对短的代码片段。复赛难度提高,特别是最后一题的内存分配器,我尝试了 c2rust 库,但由于需要一些改造才能适配,最终失败了。通过这一个多月的学习,我对 Rust 有了初步的了解。

操作系统训练营阶段

2024年11月-12月,我参加了操作系统训练营,学习了 rCore 的基本原理和实现和组件化操作系统的设计和实现,并且在项目阶段参加了对应用的支持。训练营的专业阶段和项目基础阶段中,我学习了如何从零开始实现一个 Rust 操作系统,以及在此之上拓展到 unikernel 和宏内核。我完成了这两个阶段的课后练习,加深对 Rust 和操作系统的理解。训练营的第四阶段中,我选择了在 new Starry 上支持 Python。经过一段时间的 debug 以及和同学的交流后,实现了在 new Starry 上运行最基本的 Python 测例。通过两个月的学习,我对 Rust 操作系统有了基本的认识,并且获得了一些实践的经验。

Starry 实践阶段

2025年1月-4月,我参与了 starry-next 的开发。一开始是熟悉 starry-next 的代码结构,通过运行并尝试补充实现2024年操作系统比赛的测例来加深理解,在这个过程中我也参考了其他同学的一些实现。开学之后的工作转移到在四种硬件架构上通过2025年操作系统比赛的测例,比2024年的测例多了许多。我与大实验和本科毕设的同学一起开发。3月中旬之前主要专注于 basic 测例的实现,一开始2024年版本的 starry-next 可以通过所有的测例,但 2025 年版本代码改动,所以花了一些时间去适配。之后专注于 libc-test、busybox、lua、iozone 测例。除了硬件层面的问题,大多数测例实质上是要完成一些 syscall,以及可能对操作系统的一些组件的改动。一开始我主要负责若干个文件系统相关的 syscall 的实现,但随着开发的进展,涉及的 syscall 也不限于文件系统。在这个过程中我学习了许多其他同学的实现,也向主线提了一些 PR。4月底,我一直在尝试实现 iozone,目前定位到原先无法通过测试的原因是共享内存和 select(实际 iozone 调用 select 是为了 sleep)未实现,而目前粗糙的实现依然存在 iozone 会不断调用 select 陷入死循环的问题,有待进一步排查。

学习成效

Rust 学习方面,通过了训练营 rustlings 的所有练习,通过了 Rust 比赛的初赛所有题目和复赛除了最后一题之外的所有题目,获得优秀奖。

操作系统方面,完成了训练营的所有练习,为 starry-next 和 ArceOS 提了若干个 PR,最终能通过2025年操作系统比赛初赛的大部分测例。

问题和解决

第一是语言问题,一开始学习 Rust 的时候虽然过了一遍内容,但并没有完全理解,在后续开发的时候依然会遇到一些看不懂的报错,只能上网搜索。但是语言的学习确实也只能这样,在运用的过程中记忆。

第二是环境和开发方式问题,我尝试了许多不同的环境,包括 WSL、GitHub codespace、阿里云服务器、实验室服务器等,以及在其上的 Docker 环境。starry-next 的配环境确实有点麻烦,另一方面也是我自己对于容器环境的了解不够深入。最终我选择在实验室服务器上自己配环境,以及在 GitHub codespace 用其他同学写好的配置。

第三是开发过程中遇到的各式各样的操作系统的问题,也是我需要实现的地方,比如 glibc 的 tmpfile 函数依赖 fcntl 函数的 F_GETFL 参数,比如 fstatat 函数中 to_string 函数会在字符串后 padding,导致 utf-8 解析错误,比如 glibc 的 fstat 函数调用的是 fstatat 函数,而代码中在unlink 之后依然用文件名访问等等。这些问题都在我阅读代码和 man 手册后得到解决。具体问题和解决过程见 starry-next 宏内核扩展实践记录

下一步

2025年4月开始,我补充学习了操作系统训练营中之前没有学的虚拟化章节,并且通过阅读 axvisor 的代码和文档来进一步学习虚拟化。接下来我将参与到组件化虚拟机方面的实习研究工作中,从 riscv 入手,逐步延伸到 aarch。

  • 总结

​ 第一阶段是对rust的系统性学习,主要结合习题了解相关语法语义以及特性。
​ 第二阶段结合实验指导书,对操作系统基础知识展开系统性学习。ch1跟随指导构建裸机环境,了解一个helloworld程序如何脱离标准库在开发和运行。ch2了解特权级切换相关的一些寄存器的功能,以及特权级切换的执行过程。ch3实现了一个简单的sys_trace功能,用于记录和返回系统调用信息。ch4了解sv39多级页表的字段意义和功能,学习rcore中内存管理机制,实现内存映射功能。ch5学习rcore的进程管理机制,实现进程创建并执行的功能,学习实现stride算法。ch6学习easy-fs文件管理机制,实现文件硬链接计数和返回文件节点属性的功能。ch8学习了三个同步互斥机制,实现了基于mutex和信号量的死锁检测机制。
​ 第三阶段结合课程视频和PPT内容,对arceos进行简单的学习。基于已经实现的功能,完成一些比较简单的功能的实现。print_with_color修改println宏,加入了颜色显示功能。support_hashmap基于Vec和BTreeSet手动实现一个hashmap。alt_alloc结合PageAllocator和ByteAllocator实现了一个双端分配器。sys_mmap实现了一个内存映射的系统调用,加载文件内容,虚拟内存映射到物理内存。simple_hv简单的对加载过程中的a0和a1进行设置。
​ 经过前三个阶段的学习,初步积累了对操作系统的一些非常粗浅的认知,还缺乏一个比较全面的系统的了解,管中窥豹。希望在第四阶段的学习中,自己能够戒骄戒躁,加深学习,提升自己。

第一阶段总结

第一阶段写了rustlings,以前就写过一遍,不过这10个数据结构题还是挺折磨的,跟编译器搏斗。

第二阶段总结

第二阶段写了rCore的lab,以前看过一半xv6的lab,但是已有的代码看不太懂,最后烂尾了。感觉做这种OS lab最大的困难就是充分理解框架代码,好在rCore的指导书足够详细,代码也比xv6简单一些,最后做完了,写的过程比较顺利,除了最后一个检测信号量的时候,对信号量的更新和对检测用的数组的更新顺序顺手写反了,卡了一天半。。。看指导书的时候记了一些笔记在我的blog上,学到了很多写rust的技巧,闭包、链式调用之类的,以前对OS只有理论上的积累,写完之后也有了一些实践经验。

第三阶段总结

第三阶段正式接触到 ArceOS,写了6个小练习,感觉难度都不大,设置练习的目的应该是熟悉 ArceOS

  • print_color:在 putchar, println!, 或者 print-colormain 函数里改一下,加入颜色代码的部分就好了。
  • support_hashmap:考虑到手搓一个 hashmap 比较麻烦,而且这也不是OS训练营的重点,直接把 hashbrownhashmap 拿来用了。
  • alt_alloc:bump非常简单,byte_pos 从前往后,page_pos 从后往前,把对应的接口实现完就好了。
  • ramfs_rename:找到目录下名为 old_namenode,然后先从这个 dirindex 中删除 (old_name, node),再插入 (new_name, node)
  • sys_mmap:找到一块可用的内存,设置好映射,把文件的内容读取进来即可。
  • simple_hv:改一点异常处理函数的分支,跳过异常并把 sepc + 4,第一次了解到 hypervisor 都干了什么,以前只听说过这个名字。

然后又过了一遍 ArceOSdeepwiki,接触到了“模块化”这个概念,感觉挺有趣的,和rust的 module 很好的结合在了一起,降低了不同部分之间的耦合,用户程序通过用户库的 API 找到对应的 module。在构建内核时像搭积木一样选需要的部分,在一些嵌入式场景中可以量身定制,想要扩展成宏内核也很容易,可维护性也很高。

一阶段 Rust

Rust程序设计+Rust圣经+Gpt 看任意一本书基本题几乎都能做出来,个别疑难杂症问ai让它讲清楚当前的问题是什么。

二阶段 Rcore

这一部分内容重点在文档阅读,了解每一部分的数据结构设计以及底层接口实现,实验大都有类似的已经实现的功能函数作为参考。

Lab1

sys_trace:
当前所有任务均由任务管理器管理,每个任务均对应一个任务控制块。修改任务控制块数据结构新增系统调用记录数组,系统调用时修改对应任务控制块的系统调用数组。

Lab2

sys_get_time和sys_trace: :
这里引入了虚拟地址空间,存在地址空间隔离。该系统调用接收的地址是虚拟地址,需要通过访问当前任务页表获得真实的物理地址才能实现数据的有效写回和读取。
mmap 和 munmap 匿名映射:
map和umap的下一层接口均有实现,只需要找到然后调用。
踩坑点:这里的传入地址使用是start上取整end下取整形成一个range,这里看似下取整时多取了一页但是其实这是一个左开右闭的区间看起来多取的一页不会被使用。

Lab3

spawn 系统调用定义:
仔细观察fork和exec的实现可知道exec修改的东西很有限将这一部分修改直接替换到fork中就能实现spawn要求的功能。
stride 调度算法:
同样是修改任务控制块维护优先级stride等数据,优先级调度逻辑的具体实现在fetch函数中,当需要从任务队列中去出一个任务时先遍历一遍任务的stride,选取其中最小的来执行。

Lab4

sys_stat:
通过文件描述符获取对应的Osinde,然后向下访问获取信息。
sys_linkat:
在根目录下根据oldname找到对应的inode,复制一份inode并于newname构成新的目录项。
坑:这里维护链接计数是通过遍历根目录查找相同inode实现的,另一种方法是在磁盘的inode里面维护一个链接计数,但是没有找到相应的方法实现也没有实现思路遂没有采用。
unlinkat:
在根目录下直接删除对应项

Lab5

死锁检测机制:
感觉没法避免死锁只能避免进入死所的状态(可能理解有误)。

三阶段 Arceos

有roce的基础三阶段感觉还是比较轻松的

exercise print_with_color

使用 ANSI 转义序列即可

exerxise support_hashmap

这里是使用拉链法实现的一个hashmap

exersise alt_alloc

比较简单按照算法描述实现即可
坑:这里维护内存块的时候不要用Vec,使用数组或者链表即可

exercise ramfs_rename

在axfs_ramfs下作修改为DirNode 实现rename方法。实际上就是根据名字remove对应的inode,然后合并新名字再插入回去。
坑:这里首先要到根目录去patch一下axfs_ramfs依赖,修改依赖成功后报错仍然会是unsupport,实现rename方不报错。

exercise sys_map

先开一个缓存数组把文件内容读进来,然后在userspace中查找尚未分配的area,为该部分area的虚拟地址建立物理映射。然后调用函数将缓存区的文件内容写入到完成映射的虚拟地址空间。

exercise simple_hv

为sepc添加对应的指令偏移然后修改寄存器
坑:不知道为什么需要在两个trap下的代码完成后提前return false而不能等match结束返回false,不然就会卡死。