0%

OS Summer of Code 第一阶段总结报告

首先自报家门,我是在来自上海科技大学信息学院的张18级本科生张驰斌。了解到这一次实习机会是通过大群里面一位同学发的消息。原本自己也对“用Rust在RISC-V机器上面写一个OS”这样新技术的梦幻联动也有过畅想过,加上对计算机底层知识比较感兴趣,没有多想就报名了。

Read more »

活动总结

前言

我是徐文浩(freheit889),在学习ucore的过程中,我在群里突然发现了这个活动,当时心中一阵雀跃,后来一看要简历,想着我那么菜,怎么搞啊。后来仔细想想,投了又不亏,当时就决定要投,
后来紧张了两天,居然进来了,当时的心情是 o( ̄▽ ̄)ブ,在期末考试的重压下学习起了rust.

Read more »

前言

2020年6月30日,在年级群看到了一位同学发的 OS Tutorial Summer of Code 链接,拍拍脑袋,决定利用这个暑假参加这次活动。
原因要追溯到上个学期,也就是大二上学期,的末尾,第一次在我的笔记本电脑上装了 Linux 双系统,从此就喜欢上了 Linux,一发不可收拾,这种兴趣逐渐使我萌生了动手写 OS 的想法,但一直以来都没有一个完整的知识体系和现成框架,这让我无从下手。
从那天开始,这个活动带我进入了一个新的世界,一个关于 Rust 语言,RISC-V体系结构,和新时代操作系统的新世界。

Read more »

从8月初开始,我从0开始学习了一周的rust语言,完成了相关练习。学习rust的公开repo为:

https://github.com/gystar/HelloRust

之后开始跟着rCoreTutorial的实验指导完成了lab0-lab6,从简单的中断到内存管理,再到进程的创建和调度,最后是系统调用和设备树,将一个小型os内核用rust语言一步步的构建出来,还是挺有成就感的。对于os的原理有了比教科书要深刻得多的理解,感觉从中获益良多,感谢各位老师和助教。学习rCore的公开repo为:

https://github.com/gystar/rCoreTutorial

并且我完成了所有的实验题目。其中,我感觉比较难写的是伙伴分配算法,难点在于:

  • 完成传统的伙伴分配算法
  • 分配的地址有对齐要求,因此可能要检查空闲表的多个链表的多个结点
  • 由于此算法是用于动态内存分配,所以一开始不能直接使用动态分配内存的数据结构,如linkedlist,否则陷入互相new的死锁。但是此算法本身是基于链表实现的,因此我实现了一种新的链表:一开始分配一个静态结点,之后的结点在堆上动态分配的链表。伙伴算法,最开始每个链表最多一个结点,因此这个链表是刚好满足要求的。

  • 题前

    学习os一年,看过两个教程哈工大的linux0.11和清华的ucore,拿起放弃好多次,算是坚持下来入门了。一直以来想写个简单的os,奈何功力尚浅,迟迟不敢动手,今年有幸参加了summerofcode2020线上学习,对我来说是个很不错的实践机会,开始动手,边学习边搭建自己的os环境,为后期学习高级操作系统做准备
  • 总结

    本次实习要求用rust+riscv实现os,对我来说都是新知识,就按部就班的按照step0的要求建立自己的学习步骤,rust看了下语法后直接实现基本的数据结构,os中的页面分配算法,调度算法等本质就是对基本数据结构的操作,算法原理不是很强。收获比较大的是学习riscv汇编吧,我以为我会被这个困住,像当初学习Intel和AT&T汇编那样,是刚开始我在尝试写第一个riscv汇编时候遇到点问题,后面学习csr特权级指令没遇到什么问题,以后再学习汇编指令啥的不会是什+么问题了。其次逼着自己看youtobe视频教学(riscv如何控制SiFive闪烁灯),国外视频似乎不是很难了,毕竟我英语听力一塌糊涂。
    os方面,基本来说就那几块,中断,系统调用,进程线程管理这几块原理代码我在学其他os课程时候理解了,剩余的就是内存管理部分,这部分主要是页表的建立,学哈工大的课程时候有个实验是根据虚拟地址查看物理地址,并读取物理地址的值来直观感受MMU翻译过程,本次中也试了下,rust写os内存管理这部分确实简单多了,通过本次学习弥补了不少以前的知识盲点,还有一个就是设备的管理,这两块通过这次实习消除了不少盲点,其他方面就是巩固了OS的一些基础知识
  • 展望

    本次实习对我来说帮助很大,学到不少知识。从实习的实验项来说,确实不多,我只完成了实验指导0-6步,其他的本来想留出一周时间来做下,没时间了。不过这没什么,一开始我就想的就是按照实验指导书后的步骤从0一步步搭建到6,通读下rcore-tutiorial代码以及想清楚这么设计的合理性。接下来的时间,我打算去迭代下本次做的这个os,学习os没什么捷径,只有一句话,绝知此事要躬行!!!
  • 相关 repo

第一阶段

算是完成了100道题,但感觉多线程,闭包的掌握还太差,函数式编程有点新奇

第二阶段

lab1

读了一遍guide后接触项目时有点不知所措,参考了blog再加上自己的思考后慢慢地才感觉有点掌握了实验
完成了lab1,感觉思路上并不难,其中的链接,特区等级的切换等仍需仔细研究。

lab2

感觉lab2代码量十分的大,我花了大量时间来理解代码,这是我花费时间最长的实验,仍感觉部分理解不透
最后感觉实验逻辑比较简单,发现位运算的漏洞,该写datalab了。
还有个println调试导致的乌龙,该学gdb了。

lab3

lab3感觉比较简单,就是修改了一下idle,spwan的逻辑理解fork和exec后并不难,而且和new几乎一样。

一些感想

  • 通过这个实验,我基本了解了Rust语法,Risc-V以及简单os的设计
  • 我的基础技能有欠缺,比如多线程等,及时补上
  • book仍需细读,写完后续实验
  • 非常感谢老师同学们对我的帮助

前言

大家好,我是姚宇飞,非常高兴能参与到这次 os tutorial summer of code 的活动中来。我来自哈尔滨工业大学(深圳),目前大二。

在参加这次活动之前,我虽然对rust和risc-v并没有过多了解,但是我却对操作系统有着浓厚的兴趣,在学校还没有学习到相关内容之前,我就已经自学了os原理和linux内核设计

总体上来说,这次的第一阶段学习过程还算顺利,初步学习了Rust并且了解了 RISC-V 指令集的实现。从零开始,一步一步完成了一个简单os的设计,我还尝试为实验提供的os代码进行了自己的改进和功能添加

以下是每个阶段的总结,也希望和大家分享一些自己的学习经验。

Read more »

阶段一总结

第一部分 Rust语法

在这一阶段,主要任务就是熟悉 Rust 的语法。

Rustlings

首先是 Rustlings 的练习。作为颇负盛名的 Rust 入门练习,起到的效果也是极佳的,尤其对于我们这种拥有其他语言基础的人。

题目虽然看起来挺多,而如果没有太多不懂的地方的话,每道题的用时都不会很多。只有许多不常用的功能才需要频繁的查阅文档。同时也能提高我们查阅 Rust 文档的能力。

相较而言,Rust 的 API 文档比较好理解。不过其中的 Trait 方面容易被忽略,查阅起来还是要费一番功夫的。

Rust By Example

在例子中学会 Rust,也是比较推崇的一个方法,效率比单纯看 API 高效,也比单纯看别人源码来的轻松。这本书适合结合 API 文档使用,尤其是当 API 文档中的例子不够详细的时候。

Learn X The Hard Way + 自主练习

在做”笨方法学xx“系列时,其实感觉效果很差,里面很多都是鼓励我们直接使用现有的 API 来开发,不够底层。与此同时,C 语言中很多简单的语法,在 Rust 中都需要绕几个弯路才能实现,也带来的不便。

而如果选择 Python 版本的练习题,又会受限于 Python 频繁的”调包“特性,对学习 Rust 其实帮助不是很大。

于是自己选择了一些 Leetcode 上的题来练习手动实现数据结构。由于主要为了学习 Rust 的语法,因此并没有选择困难的算法题,而是选择了两三道普通的中等题来练手。

此外,为了详细了解 Rust 如何凭借 Unsafe 块,达到 C 语言同等的能力,还翻阅了 Rust 中对 LinkedList 的实现,了解了 Unsafe 使用的方式和技巧,并自己实现了一个链表数据结构。

第二部分 RiscV指令集

这一阶段主要着重于对 RiscV 指令集的熟悉。主要的材料就是 RiscV 的官方手册和中文手册。

RiscV 的指令大部分都是定长的。这样有利于 CPU 高速读取指令并且修改 PC 的值。

RiscV 的指令都是经过良好设计的。每个指令中的部分,都能获得很好的利用。

RiscV 中关于特权级的部分十分清晰,对设计系统而言起到帮助。关于 U, S, M 三个态的特权级切换和特性与功能,都在手册中得到的良好的阐述。关于页表切换的部分,也有足够长的篇幅进行描述。

第三部分 Lab实验

Lab 0

主要用于熟悉一下如何通过 Rust 的工具链来生成一个最简易的内核,为之后的步骤作铺垫。

在这一步,我们舍弃了 Rust 的运行时,同时切换到 RiscV 指令集下的工具链。

之后需要通过链接器,将我们的内核起始地址,放到 0x80200000 处,也就是 Qemu 调用我们内核的地址。

通过上述的步骤,最基本的 Playground 就已经搭建好了。

Lab 1

实现了中断处理机制的基本。

这一步主要通过和 RiscV 的中断机制相互结合,实现了内核中的中断机制,并且分别为几个中断事件实现了简单的中断处理程序。

同时,还将上下文的概念引入到内核中,使我们能够备份程序的运行状态,也为之后的实验做基础。

我们实现的中断中,时钟中断是最重要的。时钟中断将允许我们在之后进行线程的切换,也是计算机中并行的一种体现。

这一章的实验题,让我们自己捕获一种新的中断并处理,同时希望我们能够触发这个中断以验证。

Lab 2

建立起动态内存分配的机制,通过分配器来动态分配页帧,使得我们可以在内核运行过程中使用动态增长大小的数据结构了。

在这里,我们将物理地址具象化为一个结构体,为我们看待地址空间提供一种新的方式,也为下一章节引入虚拟内存作铺垫。

这一章的实验题,希望我们亲手实现一个物理页米分配算法或者堆分配的算法。

Lab 3

实现 Sv39 标准的页表机制。通过引入页表,并且开启 RiscV 中的 Sv39 的页表机制,我们实现虚拟内存的概念。其中,我们查询、建立和修改页表以适应我们的需求,让每个线程看到的地址空间几乎都是独立的。

同时完善了内核重映射的过程。为了将我们的内核成功地放置于虚拟空间的高地址处,我们通过临时的页表,使得我们能够将内核的虚拟地址转移到高地址处。

这一部分的实验题,要求我们自己实现一个页面缺页置换算法,并且需要使用到第 5 章的有关文件的内容。

Lab 4

本章节完成线程概念的实现,使运算资源能分到各个线程上去。

我们将线程中的信息统合为 Thread 结构体,并通过修改时钟中断历程,结合线程调度器,做到不同时间运行不同的线程,以分摊运行时间。

为了使我们在时钟中断的时候,内核能够拥有稳定的栈空间,而非使用程序的空间,我们还指定了程序中一段空间作为内核栈。

这一章的实验题,一部分在于通过获取键盘输入(第 5 章的内容)来响应线程中断和线程克隆的事件;另一部分在于自己实现 Stride Scheduling 的调度算法。

Lab 5

这一章配置 Qemu 挂载支持 VirtIO 协议的设备,同时通过现有的 rCore-fs 工具,实现特定文件系统的访问。

这要求我们熟悉设备树的概念,并且了解 VirtIO 的协议。了解我们的系统如何通过 DMA 来获得对应设备的信息。

同时,还要拥有最基本的文件系统知识,能够清晰对文件访问的过程。

Lab 6

这一章相对较于杂糅,不仅实现了 ELF 格式文件的读取,还实现了少数的系统调用,同时还完善了条件变量的机制,以实现更好的线程调度功能。

我们通过调用现成的 ELF 解析器,能够做到读取 ELF 文件的信息,并且将系统的控制权交由 ELF 可执行文件来运行,也就相当于允许用户程序的运行。

同时,为了让用户进程更好的运行,我们还实现了几个系统调用,并提供其接口给用户进程,逐渐建立起了用户的框架。

此外,为了更有效的分配运行时间,还添加了条件变量的机制,使得系统不需要理会睡眠中的线程,更有效的分配运行时间。

这一章的实验题基本上重点在于自己实现几个系统调用,以供用户使用。