首先感谢各位老师以及同学提供的如此丰富的Rust与操作系统相关的学习资料,令本人受益匪浅,下面是本次训练营的总结报告。
第一阶段,Rust语言学习
通过阅读《Rust程序设计》和在线网站Rust Book,加深了对Rust语言的部分理解,特别是生命周期、所有权以及异步等部分。相较于之前所接触过的Java、Golang等语言,在理解上述部分确实有一定难度,但通过Rusting和一些练习,进行实际编码操作等,理解了Rust为什么这样设计,也反思了在使用其他语言编码时所忽略的异步竞争等问题。
第二阶段
Lab1
- 学习了程序在没有文件系统的情况下是如何加载入内存的。
- 任务可以通过
yield
主动让出cpu,也可以利用时钟中断和计时器,通过每隔一段时间中断一次当前程序,并切换到下一个程序,实现公平分配的时间片任务轮转调度算法。 - 在
TaskControlBlock
中添加pub syscall_times: [u32; MAX_SYSCALL_NUM],
用以保存系统调用计数,添加start_at: usize
字段保存任务开始时间。
增加get_task_info
函数,获取当前任务,并将任务状态、调用次数、持续时间输出,以此实现了实验任务要求。
Lab2
- 这一章节初看起来内容较多,多级页表的代码较上节复杂许多,但是慢慢梳理,从
ptr->VirtAddr->VirtPageNum->PhysPageNum->FrameAllocator->PhysAddr
一系列的调用、转换看过来,层次还是清晰明了的。
- 首先,需要获取虚拟地址所在的虚拟页。这可以通过
VirtAddr::floor()
方法来实现。 - 接着通过
Task
结构体中memory_set
字段中的page_tables
找到对应的物理页表。 - 最后,需要计算物理地址。这可以通过将页表项与虚拟地址进行按位异或操作来实现。
引入页表后,跳转指令实际被执行时的虚拟地址和在编译器/汇编器/链接器进行后端代码生成和链接形成最终机器码时设置此指令的地址是不同的。rCore通过增加的一种跳板的方式,解决了分时多任务问题。
再回到作业题目上来,在
MemorySet
中添加anonymous_data_frames: BTreeMap<VirtPageNum, FrameTracker>
字段,用以保存申请的物理frames,添加两个方法:mmap munmap
,仿照MemoryArea
中的同名方法,实现了虚拟地址到物理地址的映射,并使用BTreeMap来持有Frame的所有权,避免被释放,而在调用munmap方法时再手动放弃所有权,释放内存。
Lab3
- 这一节主要利用
Processor
来实现任务调度的idle控制流,配合之前实现的Task,通过创建Task来创建一个新的进程。在Task中增加一些信息字段,用以储存子进程、父进程、当前进程信息等。为实现spwan系统调用,参考学习了实验文档中user_shell的实现,利用现有的fork与exec来实现要求。 - 在
TaskControlBlockInner
中添加stride调度所需要的字段,修改TaskManager
中获取下一个任务的逻辑,以满足算法要求。
Lab4
未完待续。。。