-
Notifications
You must be signed in to change notification settings - Fork 452
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #185 from EastMonster/master
[23/11/11] Blog of EastMonster
- Loading branch information
Showing
1 changed file
with
52 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
--- | ||
title: 2023秋冬季开源操作系统训练营第二阶段总结-EastMonster | ||
date: 2023-11-11 15:46:00 | ||
categories: report | ||
tags: | ||
- author: EastMonster | ||
- repo: https://github.com/LearningOS/2023a-rcore-EastMonster | ||
--- | ||
|
||
### 前言 | ||
前前后后入了几次 Rust 的门,都以失败告终。这学期课排得少,很闲,一开始是选择做 jyy 的 OS 实验,后来在菜鸡取暖群中看到这个训练营的信息,遂跑路开始做这个。 | ||
第一阶段的话,因为以前做过 Rustlings 做到差不多一半,所以还是比较轻松的,然后就开始摸鱼了(逃) | ||
|
||
### 第二阶段总结 | ||
学校的操作系统课教得比较水,而且以理论偏多,也有我自己不认真学的原因,最后效果比较差。能从理论和代码层面逐渐实现一个操作系统,对我来说是一次崭新的体验。现在~~磨洋工磨了三个周~~做完三个实验之后,作关于第二阶段的总结。 | ||
|
||
一开始配环境的时候碰了点壁,当时想在 Arch 下面做,但是 Qemu 太新了,旧版源码也编译不了,最后还是重回 WSL 的拥抱... | ||
|
||
#### Chapter 1 | ||
第一章讲述了怎么写一个 Bare-metal 应用,涉及到了一些内存布局、汇编、链接器之类的知识,好在之前看 CSAPP 是看过相关内容的,所以压力不大。不过一上来面对这些东西,对一些概念还是有些模糊或是错误理解。比如内核栈其实一直都是放在 `.bss` 段的,我老以为它在别的地方,这一点我直到第三章才弄清楚... | ||
|
||
关于脱离操作系统和标准库的依赖来写一个程序这件事,心里却没有太大波澜,因为我之前也看过一点 [BlogOS](https://github.com/phil-opp/blog_os), 那个是在 x86 上实现的。接触一个较新的体系结构对我来说挑战会更大一些。 | ||
|
||
#### Chapter 2 | ||
第二章,批处理系统。看到这个名词我脑海里浮现的就是那种几十年前的大型机...不扯别的了。这一章的重点是特权级和 Trap 的管理, 这部分的汇编确实得慢慢消化。在看最后一节的前半部分的时候我都在想,要怎么执行第一个应用呢,我的最初想法就是直接把 `pc` 跳到初始地址,其它的寄存器该保存保存,也不需要转换特权级。看到最后,通过构造特殊的 Trap 上下文来使程序运行的做法给我留下很深印象,这也是特权级的意义所在,用户态就该乖乖跑程序,切换应用是内核该做的事。 ~~(主要当时忽略了内核开始运行时是在 S 态下的,不 `__restore` 也进不去 U 态)~~ | ||
批处理虽然比较过时了 (个人理解...), 但是这里涉及到了重要的概念,给后面的章节做下铺垫。 | ||
|
||
#### Chapter 3 & Lab 1 | ||
第三章,从批处理变成了分时多任务,这一次多了**任务切换**的概念,在两个 Trap 控制流间跳转,达到切换应用的目的。同时也引入了时钟中断,感觉和之前学过的理论知识串起来了。 | ||
|
||
实验一,这个的实现就是在 TCB 里面加字段,加一个返回相应字段的函数,并在调用 syscall 的时候加个计数,没了,还是比较简单的。 | ||
|
||
#### Chapter 4 & Lab 2 | ||
第四章,引入了页表。我在这里头疼了很久。页表的设计很巧妙,同时也是在这一章,编程语言带来的优势体现得淋漓尽致。比如同样是 `usize`, 但是都可以包一层变成不同的类型 (`VirtAddr`, `PhysPageNum`, *etc*...),借助 Trait 机制还可以随意转换。虽然 C 也有 `typedef`, 但是按这样写的话,代码肯定会相当混乱;`Drop` Trait 相当好用,RAII 比手动释放资源不知道高到哪里去了。~~写到这里,Rust 的高贵已经尽数体现了~~ | ||
|
||
这一章与上一章不同的是,因为引入了虚拟地址空间,所以在切换任务的时候页表也得一起换;内核和应用地址空间的设计也经过了精心规划,比如跳板的设计等等,以及在内核空间创建的时候就对整个剩余可用的内存段建了一个恒等映射,所以在内核里不用担心地址找不到的问题,很是巧妙。同时,在这一章的代码实现中出现了多个*平滑*的表述,让我意识到操作系统的编写需要足够细心,能洞察对切换前后系统的状态。尤其是这种涉及 xxx 切换的部分,写出 Bug 很难查。 | ||
|
||
实验二,自我感觉我的实现很丑陋。先谈重写上个实验两个系统调用的事情,现在是要对一(或两)个 [u8] 上操作。在指针指向的数据跨页的情况下我是真不知道咋办,感觉这种时候可能 C 语言更好用些。 ~~(不过不写也能过用例, 所以 `sys_task_info` 的我就鸽了)~~ | ||
|
||
分配内存的那两个调用,因为限制条件很多,体现在代码上就是一堆 if. 以及 `unmap` 的实现感觉有点低效,每删一页都要找一下在哪个逻辑段,但也想不到更好的办法了。这里还被小坑了一手,`find_pte` 就算返回了一个 `Some` 也不一定有效,还得手动 `is_valid` 一下。 | ||
|
||
#### Chapter 5 & Lab 3 | ||
第五章,任务变成了进程,这里开始有一点点知识盲区了,第一次知道 `exec` 和 "idle task" 的作用。idle 控制流就是不断循环取任务执行,每次有应用交出 CPU 使用权时,就会切换到 idle 控制流并开启新一轮的任务调度,调度算法就可以在这里做文章了。 | ||
|
||
实验三,代码框架提供的函数非常够用,所以很快就做完了。 ~~(除了一开始忘记维护父子关系有点难绷)~~ | ||
|
||
### 结语 | ||
参加本次训练营让我受益匪浅,我是越来越喜欢 Rust 了~~(同时也越来越不喜欢 Java...)~~,同时对操作系统也有了更立体的认识。写到后面,随着抽象程序越来越高,感觉和写一个普通的程序差别不大了。能优雅地构建一个精密的系统是一件多么令人愉悦的事! | ||
|
||
这一次因为前面太偷懒了,用了多达三个周的事件才草草做完三个实验。后面的时间我会做完剩余两个实验,并尽力完成第三阶段的任务。 | ||
|
||
感谢参与本次训练营的老师和工作人员,谢谢你们! |