0%

rCore OS 学习总结

本次训练营是 Rust 与操作系统的有机结合。我对 Rust 已经足够熟悉,因此侧重操作系统部分的第二阶段更加吸引我。

从一个裸机程序开始,随着需求的复杂化,我们需要逐步添加各种系统调用的实现,最终完成了一个麻雀虽小五脏俱全的操作系统。

1. 应用程序与基本执行环境

操作系统和应用一样都是软件程序。区别在于,操作系统需要几乎直接与硬件交互,不像普通应用程序可以使用标准库提供的各种功能,毕竟标准库构建在系统调用上,而系统调用又是由操作系统提供的。

在操作系统与硬件之间还有一层 SBI (Supervisor Binary Interface)。在后续的编程实验中,我们直接使用编译好的 RustSBI BootLoader 二进制文件。

RustSBI 规定了 OS 在内存中的位置,那么编译 OS 时需要调整链接器使其生成符合要求的内存布局。

2. 批处理程序

操作系统最主要的作用就是运行应用程序,而且往往是多于一个应用。一种最直接的想法是把操作系统和多个应用打包在一起,输入计算机后,依次执行每一个应用。

我们希望当应用出错时,操作系统可以继续执行剩余的其他任务。由此特权级机制被引入。

3. 多道程序与分时多任务

一个一个运行应用不够灵活,我们希望能够对多任务进行调度。那么必然就需要能够支持任务切换,即保存/加载上下文。

调度则主要有两种情况:一是任务主动让出处理器,sys_yield;二是通过时钟中断定时触发任务的切换。

4. 地址空间

操作系统和应用全都直接访问物理地址通常是低效的。引入虚拟地址机制,让每个应用都拥有逻辑上连续的大量内存,可以使应用的编写更加灵活。

RISC-V 64 平台采用了 SV39 多级页表机制,通过 satp CSR 来控制是否启用。

5. 进程及进程管理

此前,所有任务都是操作系统直接管理的。我们很自然的会希望可以由任务来创建子任务,并且可以管理更多物理/虚拟资源。于是引入进程的概念。

理解进程,最核心的就是相关的系统调用:fork, execwaitpid

6. 文件系统与I/O重定向

文件可代表很多种不同类型的I/O 资源。狭义的文件系统可以对持久存储设备 (Persistent Storage) I/O 资源进行管理。

这一节,我们第一次尝试将一组功能从内核中分离出来成为独立的库,交由内核引入使用。

7. 进程间通信

进程间交换数据大大加强了程序的能力。实现进程间通信的主要方式之一是管道。

8. 并发

操作系统通过不断切换任务实现并发,因为进程间资源是相对隔离的,这种并发容易实现但开销较大。

我们想要在进程内,共享资源的情况下实现低开销的并发,这就引入了线程的概念。

一个进程的多个线程共享资源,但需要能互斥地访问资源,避免数据不一致。为此,我们可以用锁、信号量、条件变量等同步原语。

实验感想

rCore 主要目标还是实现一个 Unix-like 的操作系统,编程实验也基本都是实现 Linux 最关键的一些系统调用。

而 Unix/Linux 本就是与 C 语言一体的。这些 C 风格的系统调用接口,用 Rust 实现起来总是很奇怪,有种削足适履的感觉。

我在思考,如果抛弃这些 C 风格的接口,从 Rust 出发重新设计接口,或许可以更好地利用 Rust 的众多优秀特性。

学习总结

一直以来我对Rust表现出浓厚的兴趣,并且曾经写过一些小工具。在平时的学习中,我也尝试在操作系统方面进行一些探索,但一直没有找到Rust与操作系统如何结合的方法。

从编程语言的角度来看,C语言更像是对汇编语言的一层语法糖,它天然适合操作硬件功能的开发,各种硬件概念可以很好地使用C语言进行抽象。然而,如何使用Rust来完成相同的任务一直让我感到困惑。通过这次的培训,我对使用Rust语言编写操作系统有了初步了解,感觉非常不错。以下是我得出的一些简单结论:

  1. 内存安全:在编程活动中,内存安全问题往往难以调试且容易出现。当使用C语言时,不经意间引入内存安全问题的可能性很高,但在Rust中,由于有编译器的帮助,可以在编译阶段轻松地发现问题。

  2. 所有权系统和生命周期:它们帮助开发人员更好地控制变量的生命周期,尤其是全局变量。它迫使开发者思考如何使用和编写更安全的代码。

  3. 强类型系统:至少在安全代码的部分,可以很好地控制C语言中常见的运行时错误问题。

  4. 语言模块化设计:Rust的模块化设计使得能够更好地对系统进行抽象,将操作系统分解成各个组件,最后将它们组合在一起,使整体结构更加清晰。

  5. 文档系统和构建工具:工具如rustup和Cargo为文档查阅和工程构建提供了出色的基础设施服务。

当然,在学习过程中还遇到了一些问题,主要是因为对Rust语言本身的不够熟悉,有些用法与C语言仍存在较大区别,需要更多的练习和实践。Rust语言引入的高级功能实际上在使用上可能会带来一些成本,就像之前所提到的,C语言就像汇编的语法糖,可以直接操作硬件,而使用Rust则需要重新学习一些新的方法和技巧,学习曲线可能会较陡。

Lab总结

上周,我完成了前三个问题的编码工作,主要是体验了如何使用Rust编写操作系统,并发现了与C语言编写操作系统不同的地方。总的来说,这些都是操作系统的基础概念,在Rust语言的基础上进行了抽象和实现,我感受到了与C语言不同的体验。

关于使用Apple silicon mac完成rcore实验的方法

1.选择docker会比vmware更好

如果使用8g内存的m1 mac来做实验的话推荐使用docker来做,相较于vmware来说docker的内存占用会更低一些(8g内存开个虚拟机和vscode挂几个网页基本上就压力就变黄了,要是再挂着qq、微信可能会直接变红),另外我的vmwaretools安装了也无法正常使用,我想在虚拟机内使用宿主机代理折腾了几天也没能实现,但是在docker上就很容易成功,还有就是arm64linux的软件支持比较少(科学上网方面),docker上的环境配置见 https://docs.qq.com/doc/DWW1GZ3FQekx5dm9T 第24个

2.在mac上直接配置环境(不建议使用)

官方的文档里说可以直接在m1 mac上跑rcore,我成功跑通了,首先需要下载和编译riscvtools,
下载得科学上网并且非常耗费流量(我使用镜像失败了),编译这个过程得花费一到两个小时,我试过使用他们编译好的但是无法运行,具体步骤可以参考 https://cloud.tencent.com/developer/article/1939023  然后就是下载依赖 
brew install gawk gnu-sed gmp mpfr libmpc isl zlib expat
以及qemu建议选择qemu7.0.0(老版本qemu需要补丁 https://github.com/BASARANOMO/xv6-labs-2020/issues/1 )
接下来具体步骤可以参考实验书以及
https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html#prerequisites
make这步由于mac上的make只有老版本所以应该得使用gmake
make -j$(nproc)   //这步需要先安装nproc,如果这步使用make报错了的话使用gmake
接下来就可以克隆仓库运行了,跑ch1没有任何问题但是我运行后面几个实验的时候经常会遇到报错,网上也没有解决办法,所以不建议使用这个方法

ch3

第一个实验要实现sys_task_info系统调用,首先在TaskControlBlock中添加syscall_times和start_time,同时在new中更新添加,接下来要实现系统调用次数信息的更新,我在内核的调度函数 run_next_task 中增加了一个简单的判断逻辑,以确定是否是进程的第一次被调度,并在需要时初始化 start_time。

ch4

第二个实验需要重写 sys_get_time 和 sys_task_info, sys_get_time 的主要功能是获取当前时间并填充传递给系统调用的 TimeVal 结构。首先获取时间戳,然后将其转化为秒和微秒,填充到 TimeVal 结构中,最后将数据复制到用户空间的 ts 指针所指向的内存区域。sys_task_info 用于获取当前任务的信息,包括任务状态、系统调用次数和任务运行时间。首先通过相关函数获取这些信息,然后填充到 TaskInfo 结构中,最后将数据复制到用户空间的 ti 指针所指向的内存区域。

ch5

第三个实验要实现 spawn 系统调用,首先,获取当前任务的控制块 task。使用 translated_str 函数将传递的路径 path 转化为字符串。检查是否可以找到与给定路径匹配的 ELF 数据,如果找到了 ELF 数据,就继续进行后续步骤,否则返回 -1。
用 ELF 数据创建新的内存集合,为新进程分配一个进程 ID(PID)和一个内核堆栈。接下来创建一个新的任务控制块,该控制块包含了新进程的信息,如 PID、内核堆栈、内存集合等。将新任务控制块添加到当前任务的子任务列表中,表示当前任务是新任务的父任务。最后,将新任务添加到任务管理器中,并返回新任务的 PID。关于stride调度算法实现我参考了
https://hangx-ma.github.io/2023/07/07/rcore-note-ch5.html

2023rCore训练营二阶段总结

序言

其实去年刚学 Rust 的时候就有看到这个训练营,感觉用 Rust 写操作系统很有意思,可惜当时没有任何操作系统和体系结构基础,有畏难情绪,所以没有参加。(现在看来其实当时就应该参加,rcore并没有想象中的那么难)

今年正巧在刚做完 xv6 的时候再次看到了这个训练营,想着继续巩固 OS 知识的同时还能重温半年多没写的 Rust,就报名参加了本次训练营。

可惜今年参加的时机并不怎么好,我本人已经找到了Android开发的实习,实习每天工作都挺忙的,只能周末抽时间看看录播,做做 lab。也许 Android 开发投入这么多精力学习 OS 算是有点不务正业,但我还是希望能够在本科阶段尽可能多的学习我感兴趣的 CS 知识。

ch3

ch3 还是很简单的,实现了一个系统调用计数和 task_info。所以这一个 lab 我的侧重于读实验源码。不得不说 rcore 跟 xv6 还是有很多不一样的地方的:

  • ch3 还没有涉及到进程的概念,只是简单区分了分时任务。在做 xv6 时其实我一直在疑惑多线程应当怎样实现,因为在 xv6 中只有进程,并且也只实现了进程的调度。rcore 中对分时任务的区分使我豁然开朗,其实一个线程就是一个分时任务,而进程并不是分时任务,而只是一个存放资源的结构体罢了。

  • ch3 的实验代码实现中并没有一个 shell 用户程序,而是直接将程序分段直接加载到物理内存中执行。这个操作我觉得其实就是在裸机程序的基础上做了一些改良,这么看来相比于 xv6,rcore 确实是在教你从零开始实现一个操作系统。

ch4

ch4 主要是学习了虚拟内存机制,其实之前学习 xv6 的时候就学得不太明白,这次算是整明白了。不过这个 mmap 相对于 xv6 那个 mmap 就比较简单了。让我比较惊讶的是 rcore 中能使用各种需要基于堆内存实现的容器(Vec,BTreeMap等)。

ch5

ch5其实难倒不难,就是需要把前面实验中实现的内容再实现一遍(直接 cherry-pick 代码不行,ch5 实验代码变化较大)感觉有点难受,并且遇到一些比较迷惑的问题时没有方法对源码进行调试(不知道是不是我没有找到,make debug似乎只能调试汇编代码)。

spawn 其实就是 fork + exec,并且不需要复制父进程的内存空间,直接 new 一个新进程的内存空间,设置一下父进程然后直接加载 elf ,搞定后再 add_task 即可。

023秋冬季开源操作系统训练营总结-lieck

在同学的推荐下,我报名参加了训练营。这次经历让我有了第一次通过代码来理解操作系统的感觉。在之前学校的课程中,我对操作系统的认识仅限于文字概念,如进程、页表和文件系统等。

在具体的实验过程中,因为是第一次编写这类 Lab,一开始感觉非常难,但是完成后巩固和掌握了很多 OS 的知识,并且在实践中得到了很大的收益。

Lab1

Lab1 需要完善系统调用。

对于 sys_task_info 系统调用,我们在 TCP 添加相应字段处理即可。

可能存在精度问题,这里我使用了 get_time_us 计算时间。

1
2
3
4
let us = get_time_us();
let sec = us / 1_000_000;
let usec = us % 1_000_000;
let t = (sec & 0xffff) * 1000 + usec / 1000;

Lab2

这部分的内容中,为 Rcore 引入了虚拟内存。

因为 Rcore 中分为内核页表和用户态页表,因此对于sys_task_info 系统调用我们不能直接通过修改参数来完成传值。需要将其转换为物理地址,而内核页表中的虚拟地址和内核地址是对应的。

然后是实现 MMap,通过 VMA 实现。

VMA 记录有关连续虚拟内存地址段信息。对每个 section ,都有一个 VMA 对象。

例如对于 memory mapped file,存在一个 VMA 与之对应,其中包含了文件信息等

mmap 收到范围和 port 后,判断是否冲突或参数错误,然后放入 VMA 数据结构中映射物理页。mummap 也是类似的操作。

在此实验中,测试数据稍弱,并没有要求实现 VMA 分裂的操作。

Lab3

Lab3 需要实现优先级调度和 spawn 系统调用。

spawn 系统调用是 fork 和 exec 的结合。可以分为两部分:

  1. 参考 fork 创建新的进程,但新进程执行的首个函数的调用 exec 的操作
  2. fork 后的子进程执行的第一个操作,用于调用 task.exec

优先级调度较为简单,在 PCB 中维护 stridepass

  • 调用 suspend_current_and_run_next 时增加当前进程的 stride
  • 调用 fetch 会选择下一个要运行的进程,找到当前 stride 最小的进程即可。

因为不要求性能,我们可以简单的遍历的选择当前 stride 的值。

第一阶段

一阶段的rustlings是挺好的rust入门题目,也是没有什么阻碍的完成了100道题。

第二阶段

lab1

这一个lab没什么难度,实现taskinfo不需要太多os相关的知识。

lab2

这一个lab开始上强度了,需要弄懂很多os知识。

关于sys_get_timesys_task_info,题目有提到splitted by two pages问题,但是直接整个转换成物理地址写入也能过测试,

我理解的处理splitted by two pages的方法是,对每一个字段,获取他的物理地址,然后写入。

或者像buffers那样,直接逐字节拷贝进Vec<&'static mut [u8]>

不知道上面的方法是否正确。

关于mmapmunmap,本来是想保存在MemorySet.areas下,但是考虑到回收的内存段可能是分配的内存段的子集,要实现MapArea的分裂,还有性能问题,

就直接在MemorySet下挂一个btree管理了(感觉在mmap这种需求下抽象成MapArea反而是一种负担)。

lab3

lab3感觉比lab2简单,spwan直接复用TaskControlBlock::new再进行一些操作,stride也是采用了简单的实现。

本来想实现,即使stride溢出,也能选择正确的程序(无符号相减,结果转有符号与0比),因为时间问题直接用u64解决咕咕咕了。

补充

感觉test还是少了。

rCore学习记录

在Lab开始之前

配置环境

本来想直接用物理机直接进行配置实验环境的

但是ArchLinux默认的qemu版本是8.1,和仓库中rustsbi要求的版本有冲突。

所以最后还是改用了docker来搭建环境……😢

1
2
3
4
make build_docker

# 用同一个docker容器进行全部实验,不想实验一次创建一次
docker run -it -v ${PWD}:/mnt -w /mnt rCore bash

修改ci-user中的makefile

1
2
3
4
5
6
env:
rustup uninstall nightly && rustup install nightly
(rustup target list | grep "riscv64gc-unknown-none-elf (installed)") || rustup target add riscv64gc-unknown-none-elf
cargo install cargo-binutils
rustup component add rust-src
rustup component add llvm-tools-preview

rustup uninstall nightly && rustup install nightly 注释掉,避免每次本地测试的时候都下载一遍

Lab 1

lab1 本身难度其实并不大。感觉主要还是结合之前的章节熟悉一下 rCore 项目代码的整体结构,

但是由于我对系统结构还不是很熟悉,所以还是花了比较多的时间。

  • 实现 sys_task_info 系统调用:

在 TCB 中添加记录系统调用次数的信息,每次系统调用时,根据 syscall id 更新相应数据。

我这里就直接粗暴地用桶方法记录了这些信息。

后面写到 lab3 的时候,发现我之前 sys_task_info 中的获取时间的方式有些问题。正确的应该需要记录进程第一次运行的时间,然后记录时间差。

Lab 2

感觉在前三个 lab 中,lab2 算是相对比较难的一个了。主要的时间都花在了这里。

因为有了虚拟内存的机制,所以要重写 lab1 中系统调用

  • 实现 mmap 和 munmap 系统调用

    • mmap

    需要注意,port参数不能直接转成MapPermission,两者有区别,并非仅仅是类型不同。
    在进行map前,需要检查对应的虚拟内存地址是不是已经被使用过了,这里可以检查 vpn_range的 start 和 end 看看是否被使用
    下面的munmap同理

    • munmap

    基本上就是map的逆操作

可以根据代码画个结构图,方便理解虚拟内存的结构。

Lab 3

  • 实现 sys_spawn 系统调用:

感觉还是比较简单,使用 translated_str 把 path 指针转成 程序名称,然后就可以创建进程,加入进程队列。要记得把新建的进程push到父进程的child中。

  • 实现 stride 调度:

TCB 上再添加上 priority, stride 的信息,然后每次进程切换的时候更新一下。

进程插入进程队列时比较下 stride 的大小就行。

总结

回顾学习的过程,我觉得完成lab重要的是要有一个清晰的思路,明白自己要做什么,明白要怎么做,要对lab有一个整体上的认识。自己阅读代码的能力还是差了一些,以后要加强。

通过学习rCore,我感觉我对于操作系统的理解更深了,不像以前只是浮于表面,只记得一些概念,而对于操作系统的实现没有真切地感知。

最后要感谢老师、助教们辛苦的付出,让我们能够学习到这样好的开源课程,让我们有机会更加深入了解操作系统。


自我介绍

我是一个来自于山东某普通一本的学生。爱好广泛,不过最喜欢的是计算机。在小的时候就非常喜欢看数码方面的内容,比如各种手机电脑,对其中的参数,性能,价格方面都有自己的见解。也经常关注圈子的各种最新的资讯等。但由于生活在乡下等种种原因,与计算机的接触也仅限于此了,什么编程语言,操作系统几乎都没听说过,唯一擅长的就成了处理各种电脑坏了的问题。。。

来打大学之后,对计算机有了更深了一步的了解,这更加提起了我的兴趣。中途接受学校课程学过C,Java,Python,JavaScript等语言。由于平时喜欢玩Minecraft(使用Java编写), 所以当时对Java产生了浓厚的兴趣,觉得自己要好好学习Java,既能满足我对游戏上需求(为游戏编写mod), 也能成为我以后能靠着吃饭的技术。

但。。。随着我对编程语言的认识越来越深,加上种种原因,我渐渐的对Java失去了兴趣。现在看来,Python也是一门我非常喜欢的语言,但是它效率又太低。本着对编程语言的信仰,我希望能学会一门效率非常高的现代语言,现在来看,它就是Rust

与大家相遇的故事

相对来说,当今用的人非常多的Java,JavaScript,或者加上Go,这类语言现在来看就像是为写业务而存活的,他们大多出现在某产品的前端,或后端中,做成网页或者客户端。而我对于计算机的热爱并不是做网页,学到现在,相对于用这些语言写业务来说,我更喜欢原理和技术上的事情。而且我是一个喜欢挑战相对更难的事情的人(并不是说写业务简单,我只是说可能在我的视角里原理和技术上的问题是相对来说更加解决的),所以我故意没有学习搞业务的东西。

我觉得能写一个OS是一件非常厉害的事情,非常酷炫的事情,比网页要厉害得多(个人而言),正好与上学期接触了某一个课程,是与计算机组成原理和操作系统有关的课程,这激发了我的兴趣与斗志,我希望能在最后的课程设计上写出来一个简单的OS,能脱离我们现在的操作系统,直接在裸机上运行的那种。而且在这之前,我正好凭着兴趣自学了Rust,毕竟Rust靠安全和很多新颖的设计著称,而且拥有非常高的性能,我想这不写操作系统正合适!

于是我在网上搜索了Rust和操作系统相关的资料,找到了rCore和blogos, 由于先找到的blogos,于是就照着blogos做了起来。当然,结果没有那么的好,由于有限的时间,加上知识的匮乏,最终只完成到了简单的中断部分,但我觉得这是一个非常好的经历,在我真正去自己写操作系统的时候,我发现并学习到了很多很有意思的设计,而且感觉成就感满满,虽然我做的内容不多,但我觉得我收获很多。我最后也是把它交了上去,虽然是个半成品,不过毕竟时间比较短,这也不算是次的作品了。

之前看过rCore的book,上面有训练营的链接,但我每次看到的时候,都发现已经开展了一段时间了,也不知道怎么参加, 不知道确切的时间。不过在这学期,我有个朋友发了训练营的链接,正好碰上正式开启的直播,朋友知道我学过Rust,就鼓励我参加。虽然深知困难,但我觉得依然要抓住机会,于是就报名了咱们的训练营,不过有点遗憾的是我朋友并没有参加本次训练营。

第一阶段

第一阶段对我来说还是相对轻松的。。。(也许)。其实虽然开启直播后马上就开第一阶段了,但是我却还是在开启了一周后才报的名,原因是在某个小岗位上写业务相关的东西(虽然不喜欢但有时候觉得还是得写写……)。不过由于提前学过Rust,直接做rustlings就可以了,然后就是比较顺利的用半周差不多的,每天的空余时间写了写就过了,然后剩下的时间就去忙校内安排的课程了(课太多了),再加上正好体测加各种实验实在忙不过来,等再次反应过来第二阶段都过了半周了。。。

其实我还是挺愿意写一个rustlings100题的题解的,不知道有没有空。毕竟用github page+hexo搭过简单的博客,还是很愿意写这些东西与大家讨论分享的,能学的很多很多的新知识和新方法。

第二阶段

第二阶段对我来说就比较煎熬了。。。

一窍不通

毕竟前面说,等我反应过来二阶段已经过完半周了,正好有空我抽出来了很多很多时间去研究第二阶段。我错过了第一节课的直播,且正好没有录播……而且我也没找到多少关于二阶段的资源,我甚至不知道哪些是二阶段的资料,Github的那个仓库怎么用我也不知道,命令也跑不通,题也不知道是什么……反正一头雾水。而且感觉自己落下很多了,也不好意思发消息问。没办法就硬回去看群里的消息,几百条划上去从头硬看,好不容易能翻出点东西来,就去尝试了。我甚至不知道到底是clone哪个仓库,到底是自己的还是README.md里面的仓库,我寻思不管啥先拉下来再说,拉下来然后也没跑通。后来翻消息发现有指导书和一个哥们发的公众号,于是花了一天也是把环境搭好了。但之后怎么跑呢,反正也是不知道……好不容易后来看到朱老师说从某一条指令开始运行,再加上第二次直播,我立马就明白了每一条是干啥用的,后来就成功能跑起来了。

初入茅庐

后来就是针对任务书进行学习,ch1,ch2,ch3相对来说我还是容易理解的,因为之前做过一次差不多的缘故,理解起来相对容易一些。不过读代码可就没有那么容易了,太煎熬了,我刚开始学急了,不知道从哪里下手。不过现在来说好像因为过去一段时间了,不是很记得当时是啥状态了。而且当时很讨厌unsafe这种东西,但是这里又有很多这玩意,我每次都会发出疑问,我真的可以直接修改内存吗,真的可以吗,真的吗?总是就是很不习惯,因为之前也没有接触过。不过后来也是慢慢稳住了,真的要冷静下来看代码,掌握一点技巧读起来也不会那么困难。系统的主要结构都会放在结构体中,然后提供一些方法,其实无非就是那老几样,找到头找到尾,捋清了关系,程序的运行逻辑也就慢慢的清楚了。而且幸运的是,我第一次尝试make test,就直接全部通过了,这给了我非常大的信心,然后我尝试去挑战ch4……嗯……差点人直接在ch4没了。

怎么说呢,ch4我感觉确实是看book好一点,ch4之前我也是看指导书,到了ch4之后我看了一遍指导书,感觉一头雾水,就只好去硬扒代码,但这代码吃素的?直接给我上嘴脸,看的我一头雾水。而且这次我没有基础了,上次做也没有做到内存这块,这学期老师讲的也没听懂(校内),这里卡了我好久。而我这段时间是几乎天天看这个东西,课上看这个,晚上也看,看到24点,研究代码,但……效果一般。后来看群里又去扒了一遍book,半天就扒完了,豁然开朗,第二天就做出来了,如释重负的感觉。兴奋的我提交之前,提交之后又没有做任何改动摁跑了几次make test,太开心了。(而且代码里面还有一些我的心理路程和各种翻译,虽然删了一些……)

实现上来说的话,就是差不多大体搞清楚了框架,address.rs就是usize包装成了各种地址页号之类的,两个allocator感觉我说不太清楚,而且感觉可能用不到就没再继续细看,然后memory_set和page_table就关键一些,一个是页表,一个MemorySet存页表和相应的地址空间,MapArea虚拟页号的连续区间。当然,我觉得大大简化难度的是原本就提供了一些方法,我直接拿去用了。读着读着我就觉得这个insert_framed_area就很适合去做这个实验,尝试了一下测试通过了,然后接触映射的我就照着insert_framed_area反过来写了几个函数,包装了一些。然后我写代码的时候还有一点洁癖,比较喜欢整洁一点……然后不喜欢破坏原本的结构,还有封装性,我很少会把原本private的东西改成public,反正……就是洁癖……然后也是非常顺利的通过了。

渐入佳境

ch4困扰了我好几天,半周多,ch5就好很多了,ch5我仍然看的book,而且这次不是我学的相对薄弱的地址了,这次进程相关的内容我正好前一阵子做业务的时候接触过很多了,理解起来相对容易一些,然后也是差不多两天左右时间通过了,找到技巧之后,感觉一切都好了起来,而且每章的那个新增结构,加上每个结构体前面的描述,基本上不用看具体的代码就能理解个大概。不过……第二阶段结束了,勉勉强强及格吧,还是得加把劲。

未完待续

关于收获

感觉这次二阶段收获还是蛮多的。同时压力也比较大(因为一开始觉得二阶段结束没全做完就无法参与三阶段了),晚上睡觉都想这些事,不过后来宽限了条件加上实验顺利通过了一些就感觉好了。

三次实验,每次做完都很高兴很高兴,
第一次是因为调试了很多次终于能正常跑起来了,而且是一次过。这无疑起了个好头,我很想分享此次的喜悦,原本想写一个blog,帮同样迷茫的朋友度过第一关,条件就是如果我能两天拿下ch4我就写,然后……我半周多才拿下ch4,就没有后续了。
第二次是因为历尽千辛万苦终于过了ch4,相对于我一开始面对ch4的内容,毫无头绪,到大体上理解结构,非常感慨,而且离进入三阶段也非常近了。
第三次是因为能成功进入三阶段了,努力没有白费,而且自己也没有那么笨,至少及格了。

而且对于学习上,也懂了很多。一开始我总是逃避去细看代码,尤其是汇编,一但遇到难读的我就不喜欢去细看,导致我花了更多的时间,偷懒最终还是要付出代价的。
而看懂了源码,弄懂了结构,就不会出现没有头绪的感觉,而是感觉自己点子很多,实验根本不在话下的感觉。都是些很模块化的东西,而且还提供了很多现成的方法,可以去使用和效仿。
我还学会了要勇敢面对自己害怕的事情,不能逃避。这件事不光是对写OS这件事而言,其实我以前非常讨厌unsafe,关在unsafe里的东西,我不知为何就不喜欢去想它的作用,有些名字特别长的函数我就会自己觉得自己看不懂,就非常苦恼。以前我总是逃避他,越逃避它,它就越折磨你。我这次是深有体会的,就这个,unsafe,裸指针,内存分配,我硬着头皮把我只要有疑问的全搞明白了,虚拟内存这里的各种名词(我才知道好几个不同的名字指的是同一个东西),每个名词都认明白是什么意思。虽然我弄明白他们需要花时间,但是我真的弄懂之后,后面的工作会好做很多很多。

最后感谢各位老师同学举办了这次活动能让我收获这么多,同时也感谢在群里面交流和帮我解决问题的大佬小佬们。咱们国家的计算机行业有大家在,以后一定会发展的越来越好,越来越强大!!

初次接触

作为一个工作党,第一次接触OS训练营课程是通过西安邮电大学的陈丽君教授推荐的,当时看到训练营很兴奋,虽然已经作为工作党已经10多年,那会上大学没有这么好的平台和开源课程,隐约记得06年左右的时候只了解过陈渝教授的网上公开课,但是对实际做的事情并没有深入了解和学习。
这次是通过训练营可以深入学习了。陈老师的课程也越来越丰富,之前的就课程也恶补了一些,这次的训练营是以Rust为主要语言基础,循序渐进一步一部的学习OS的开发过程,主要分成三个阶段,第一阶段以rustling为基础的和第二阶段的Rust语言编程,第二阶段的Rcore的OS实践学习,第三阶段的不通选题的实现,比如ArceOS等。
对于我个人已经参加了三期。之前第一期,仅完成了rustling,第二期,尝试完成了rustling和ucore,因为对rust语言编程还是一头雾水,这次,经过坚持完成到了第二次的rcore,但是还有core 的5个大实验只完成了3个实验,虽然可以过关,还是想冲一波完成实验4,但看了两天文档,仅仅有点思路了,但是没时间完成了,先提交博客过关,只能后面找时间完成了!下面是过程中的一些即简要总结。

第一阶段总结

这个阶段前40题都是一些基本语法,有编程经验的稍微琢磨下都可以完成。等到了泛型,闭包和trait就看似一头雾水了。个人总结做题可以参考官方的手册,但是深入学习语言建议可以参照https://course.rs/basic/base-type/numbers.html,rust语言圣经比较通俗的,比较翻译的和原汁原味的编程书是不一样的,或者直接对照看英文也是可以的。
rustling在做题过程中一定要多看 lint和注释里,因为题目的目的都是里面,同时看来处理对应的参数连接,会快一点。
比如:iterators5.rs实验中,需要多查看手册,我开始移植准备用比较for循环的笨办法去实验,么有理解题目的目标的意思,花费了很多时间,即使完成了实验,但是学迭代的fold用法没有理解和掌握,目前没有达到还是浪费了很多时间,因为rust里面的迭代用的很多,需要慢慢体会,同时还是学会使用手册,只要查看下fold手册,或者浏览下迭代器的用法,就一目了然。
https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold
还有就是rust手册还是需要整体先过一遍,再去做题会事半功倍,及时不全完成,但是至少目录要过一遍。

第二阶段总结

第二阶段做的还是比较吃力,一共5个大实验,我仅完成了3个,后面两个只能等后面时间完成。
实验1,整体难度不大,目标是通过syscall实现获取系统时钟和taskinfo的信息,这个时候的rcore还是比较原始,没有MMU,没有进程只有作业的状态,因此实现起来没有内存和进程的限制,只要理解代码和流程和实验的环境就可以完成。
实验2,由于增加了用户空间和内核空间去区分,因此系统之间的调用的数据交换要使用特定的机制完成,这里主要考察了translated_byte_buffer的用法,核心是memoery_set的进制如何使用和对其理解。这里为了代码简洁也查了很多资料,最后使用copy_from_slice,也对切片的使用更深的认识,但是最后看了老师的参考代码,还是有不一样的。
实验3,群里有人说比较难,但个人认为实验难度的不能很难,因为spawn基本上相当于fork+exec,还是考察进程中memory_set,program_brk,task_cx,user_sp,等拷贝和处理
第二阶段如果有一些操作系统的基础会好很多,推荐大家阅读陈海波教授的《现代操作系统:原理与实现》通俗易懂。

总结

通过本课程,除了敲开了对rust编程语言和OS开发的大门,更多的是认识了这么多老师和同学,更加认识了自己。非常感谢清华的老师和同学能提供这样一个开发的平台,晚上各位老师的讲解和答疑,是我们一个指引,也是对我们这些初学者是一个道路的指引,相信这样的训练营将会给我们的国家带来软件的繁荣,再次感谢无私风险的老师和同学们!!!

背景

我是一名计算机专业的学生,现在进入大三上学期,学校已经安排了操作系统课程,但老师教授的偏理论性缺少实践的过程。我本来已经在学习MIT 6.S081操作系统课程,朋友推荐了rCore,采用Rust语言编写的操作系统课程,觉得非常棒交流环境很好而且是国产然后配套资源也很全,就报名学习了。一起学rCore吧!

我也认为在本科阶段,就需要认真学习理解计算机核心课程包括操作系统,应该学习计算机底层知识去了解探索计算机科学领域的魅力和故事,打下扎实基础,毕竟是计算机专业的本科生,大学毕业后可能没有足够的时间与精力去做这些事情。

Read more »