本阶段的收获
经过半月多的赶ddl(,加上老师群友们的无私帮助,我成功的完成了第二阶段的任务。
不仅对Rust的掌握程度更深了,并且对操作系统中很多概念有了实际上的理解。
包括且不限于:
- 特权态的切换
- 地址表,页表的管理
- 进程和线程的区别
- 执行流切换和恢复
- 线程调度
同时,这些知识很大程度上帮助我消除了对裸机编程的恐惧。对计算机底层的运行方式有了清楚的认知。
一个尝试-Rust in ch32v003
在前几天结束第二阶段的作业后,我是打算了摸几天鱼,正好看到桌边吃灰的ch32v003单片机。
ch32v003是一块携带了riscv指令集芯片的单片机,我手头上这块,实现了riscv标准中的mai,以及f。
美中不足的是,它只有S态和M态,并没有实现U态。
于是我萌生出想法——为什么不试试将Rust代码运行在这上面呢。
ch32-hal
Rust在嵌入式方面的库,在2024年的今天已经较为完善了。在createio中查找一番后,我看到了ch32-hal,以及与其配套的qingke-rt
ch32-hal将ch32系列的单片机的外设进行了rust封装,使得在代码中能方便的进行调用和更改
如修改SYSTICK的ctlr位,只需要以下代码
1 | SYSTICK.ctlr().modify(|w| w.set_ste(false)); |
qingke-rt则包含了运行时相关的内容,可以在main函数前添加#[qingke_rt::entry],使得该函数称为编译后程序的入口函数
并且qingke-rt也可以通过类似的方法定义中断处理函数。类似的工作,我们在rcore实验中是通过内联汇编手动修改相关寄存器实现的。
代码
以下附上一个点灯代码
1 |
|
理论和实践
之前在学习体系结构的知识时,书本上只有几张图来描述代码执行流的切换,于我而言并不直观。甚至很长一段时间我是当做文科的内容来学的。
经过了本次实验后,令我印象最深的是__switch函数,通过寄存器内容的切换,便可切换到另一个执行流上。
而执行流,在某一时刻无非是:
- pc指针的位置
- 栈指针的位置
- 若干存储在当前寄存器中的变量
而对执行流,进一步抽象成包含若干线程的进程。
对若干的进程进行管理,并为进程提供服务,就是操作系统。
文件系统
在此之前,我对ntfs之类的文件系统没有一点了解。在这次实验中,了解了一个简单文件系统的实现,并且通过easyfs实现了一些功能。
同时,简单了解到了对于硬件驱动的编写,以及将不同的硬件驱动,抽象成相同的软件内模型。在软件内进行多层抽象,每层抽象负责简单的几件事情。
这样能够方便错误判断,多层抽象的思想我最先从网络原理中了解。easyfs的实现方式,进一步的说明多层抽象在计算机软件编写中,可以称得上是最佳实践了。
进程&线程
不去亲自阅读操作系统源码,是很难对进程和线程有明确的理解的。
甚至很长一段时间,我对进程和线程并没有区分。而在OS内部,进程可以拥有多个线程,线程之间共享内存空间。
对于这点的了解,不仅是系统编程领域,对我普通的软件编程也大有裨益。