ArceOS Unikernel 总结报告
不知不觉,ArceOS Unikernel 课程的学习已经过去了一半。回顾过去这两周,我深感学习过程中的磨砺与成长。感谢石磊老师的细心指导,从基础概念入手,让我们逐渐掌握 Unikernel 的奥秘。谁曾想到,Unikernel 的设计竟如此强大。每次回顾这个过程,我都会重新阅读陈渝老师的著作《像开发应用一样开发操作系统》,从中汲取启示。我对操作系统可以如同应用一般,通过组件化思维实现感到震惊。过去曾听说过鸿蒙分布式部署等新闻,也阅读过一些关于鸿蒙的相关文章,但亲身参与组件化操作系统的学习,完全是不同于以往的体验。
课程总结
第一周练习主要包含以下内容:
- 首先,通过彩色打印 “Hello World” 和支持 Hashmap 数据类型的示例,快速熟悉 ArceOS 架构
- 接着,实现 early 内存分配算法,深入了解 ArceOS 的内存分配流程
- 最后,将协作式调度算法 FIFO 改造为抢占式调度算法,为第一周的学习画上圆满句号
通过本周学习对 ArceOS 的整体架构、内存分配及调度算法有更深入的了解。
进入第二周的练习,主要包含以下内容:
- 首先,需要准备 5 个基本实验环境,分别包括:从外部加载应用、将应用拷贝到执行区域并执行、通过 ABI 调用 ArceOS 功能、在 App 中正式调用 ABI 以及支持内核和应用分离的地址空间及切换。
- 接下来,在上述环境基础上,完成 6 个附加练习,具体如下:
- 针对第一个环境,探索如何优化加载更多应用
- 在第二个环境中,研究多应用的批处理方式
- 针对第三个环境,探讨 ABIs 的 SYS_TERMINATE 功能调用
- 在第四个环境中,实现内核与应用程序之间的通信,并支持 Hello 功能、打印字符串功能、退出功能
- 最后,在第五个环境中,探索如何实现内核与应用程序的分离,并将控制权回到 loader,再由 loader 执行下一个应用
- 通过这些练习,将更加深入地了解 ArceOS 系统的运行机制和应用开发技巧。
第二周练习题思路总结
练习 1 和 2 的思路
借鉴 Unix 协议的设计理念,将数据按照如下格式保存在 app.bin 文件中,以便 ArceOS 逐字节读取并采用循环机制顺序加载。
1 | App 数量 | App1 大小 | App1 内容 | App2 大小 | App2 内容 | ... | AppN 大小 | AppN 内容 |
通过这种设计,可以方便地管理各个应用程序的尺寸和内容,从而实现应用程序的顺序加载和高效运行。在 ArceOS 读取到相应数据后,可以根据数据内容来调用相应的应用程序。
练习 3 的思路
这道题目相对较为简单,主要需要注意一个小细节 —— noop
指令。在编译过程中,Rust
会提示不通过,原因是 typo
,多打了一个 o
。
起初,我以为该练习将 nop
指令加在 options(noreturn)
前面,但是运行的时候,程序会卡住半天不返回内核执行下一个应用。后来翻查指令解释资料,将 options(noreturn)
删除,练习 3 便顺利完成。
在这道题中,需要注意 nop
指令的特殊性质,避免使其影响到程序的正常执行。通过细心观察和调整,可以顺利解决这个小问题,进而完成练习 3。
练习 4 的思路
这道题较为简单,只需在 ArceOS
系统中添加 SYS_TERMINATE
系统调用。编写 abi_terminate
函数,并直接调用 axstd::process::exit
。接着将此函数通过 register_abi
注册到系统中,并将 abi_num
指向 SYS_TERMINATE
,如此便可顺利完成任务。
练习 5 的思路
这道题具有一定难度,非常感谢赫森
大佬在群里分享了思路。
主要思路是参考了 rCore 教程中的链接章节,并在应用层引入了 linker.ld
链接汇编。这样做的目的是将字符串从 .rodata
区域读取出来,并将原始在 ArceOS
中的相关指令移动到 hello_app
应用中。为了实现 Hello、打印字符串和退出这三个功能,我将以下指令封装到 abi_call
宏中,使得代码看起来更加简洁明了。
1 | li a0, {abi_num} |
练习 6 的思路
在完成练习 5 之后,练习 6 就会变得相对容易。主要是基于之前的 hello_app
应用进行改造,仅保留 putchar
函数。
需要注意的是,为了避免让控制权回到 loader
的条件,例如不能进行无限循环等阻塞操作,练习 5 中有一个 wfi
指令用于等待中断。只需将此指令删除,即可顺利完成任务。
以上是对 6 个练习的思路总结,希望能对你有所帮助,祝大家玩得开心 ^_^