Skip to content

Commit

Permalink
change 读者 to 同学
Browse files Browse the repository at this point in the history
  • Loading branch information
chyyuu committed Nov 7, 2021
1 parent 7caf187 commit 4fb6ebe
Show file tree
Hide file tree
Showing 27 changed files with 45 additions and 45 deletions.
2 changes: 1 addition & 1 deletion source/appendix-a/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
.. **Rust 语法卡片:迭代器与闭包**
.. 代码第 7 行用到了 Rust 的迭代器与闭包的语法,它们在很多情况下能够提高开发效率。如读者感兴趣的话也可以将其改写为等价的 for
.. 代码第 7 行用到了 Rust 的迭代器与闭包的语法,它们在很多情况下能够提高开发效率。如同学感兴趣的话也可以将其改写为等价的 for
.. 循环实现。
.. .. _term-raw-pointer:
Expand Down
2 changes: 1 addition & 1 deletion source/appendix-b/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ k210 平台上可执行文件和二进制镜像的生成流程

- 第 13 行我们使用 ``dd`` 工具将 bootloader 和二进制镜像拼接到一起,这是因为 k210 平台的写入工具每次只支持写入一个文件,所以我们只能
将二者合并到一起一并写入 k210 的内存上。这样的参数设置可以保证 bootloader 在合并后文件的开头,而二进制镜像在文件偏移量 0x20000 的
位置处。有兴趣的读者可以输入命令 ``man dd`` 查看关于工具 ``dd`` 的更多信息。
位置处。有兴趣的同学可以输入命令 ``man dd`` 查看关于工具 ``dd`` 的更多信息。
- 第 16 行我们使用烧写工具 ``K210-BURNER`` 将合并后的镜像烧写到 k210 开发板的内存的 ``0x80000000`` 地址上。
参数 ``K210-SERIALPORT`` 表示当前 OS 识别到的 k210 开发板的串口设备名。在 Ubuntu 平台上一般为 ``/dev/ttyUSB0``。
- 第 17 行我们打开串口终端和 k210 开发板进行通信,可以通过键盘向 k210 开发板发送字符并在屏幕上看到 k210 开发板的字符输出。
Expand Down
4 changes: 2 additions & 2 deletions source/chapter0/0intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ Remzi H. Arpaci-Dusseau 和 Andrea C. Arpaci-Dusseau 的《Operating Systems: Th

为应对“忽视硬件细节或用复杂硬件”的问题,我们在硬件(x86, ARM, MIPS, RISC-V 等)和编程语言(C, C++, Go, Rust 等)选择方面进行了多年尝试。在 2017 年把 复杂 x86 架构换为 简洁 RISC-V 架构,作为操作系统实验的硬件环境,降低了学生学习硬件细节的负担。在 2018 年引入 Rust 编程语言作为开发操作系统的可选编程语言之一,减少了用C语言编程出现较多运行时缺陷的情况。使得学生以相对较小的开发和调试代价进行操作系统实验。同时,我们把操作系统的概念和原理直接对应到程序代码、硬件规范和操作系统的实际执行中,加强学生对操作系统内涵的实际体验和感受。

所以本书的目标是以简洁的 RISC-V 架构为底层硬件基础,根据上层应用从小到大的需求,按 OS 发展的历史脉络,逐步讲解如何设计实现能满足“从简单到复杂”应用需求的多个“小”操作系统。并且在设计实现操作系统的过程中,逐步解析操作系统各种概念与原理的知识点,做到有“理”可循和有“码”可查,最终让读者通过操作系统设计与实现来深入地掌握操作系统的概念与原理
所以本书的目标是以简洁的 RISC-V 架构为底层硬件基础,根据上层应用从小到大的需求,按 OS 发展的历史脉络,逐步讲解如何设计实现能满足“从简单到复杂”应用需求的多个“小”操作系统。并且在设计实现操作系统的过程中,逐步解析操作系统各种概念与原理的知识点,做到有“理”可循和有“码”可查,最终让同学通过操作系统设计与实现来深入地掌握操作系统的概念与原理

在具体撰写过程中,第零章是对操作系统的一个概述,让读者对操作系统的历史、定义、特征等概念上有一个大致的了解。后面的每个章节体现了操作系统的一个微缩的历史发展过程,即从对应用由简到繁的支持角度出发,每章会讲解如何设计一个可运行应用的操作系统,满足应用的阶段性需求。从而读者可以通过配套的操作系统设计实验,了解如何从一个微不足道的“小”操作系统,根据应用需求,添加或增强操作系统功能,逐步形成一个类似 UNIX 的相对完善的“小”操作系统。每一步都小到足以让人感觉到易于掌控。而在每一步结束时,你都有一个支持不同应用执行的“小”操作系统。另外,通过足够详尽的测试程序,可以随时验证读者实现的操作系统在每次更新后是否正常工作。由于实验的代码规模和实现复杂度在一个逐步递增的可控范围内,读者可以结合对应于操作系统设计实验的进一步的原理讲解,来建立操作系统概念原理和实际实现的对应关系,从而能够通过操作系统实验的实践过程来加强对理论概念的理解,通过理论概念来进一步指导操作系统实验的实现与改进。
在具体撰写过程中,第零章是对操作系统的一个概述,让同学对操作系统的历史、定义、特征等概念上有一个大致的了解。后面的每个章节体现了操作系统的一个微缩的历史发展过程,即从对应用由简到繁的支持角度出发,每章会讲解如何设计一个可运行应用的操作系统,满足应用的阶段性需求。从而同学可以通过配套的操作系统设计实验,了解如何从一个微不足道的“小”操作系统,根据应用需求,添加或增强操作系统功能,逐步形成一个类似 UNIX 的相对完善的“小”操作系统。每一步都小到足以让人感觉到易于掌控。而在每一步结束时,你都有一个支持不同应用执行的“小”操作系统。另外,通过足够详尽的测试程序,可以随时验证同学实现的操作系统在每次更新后是否正常工作。由于实验的代码规模和实现复杂度在一个逐步递增的可控范围内,同学可以结合对应于操作系统设计实验的进一步的原理讲解,来建立操作系统概念原理和实际实现的对应关系,从而能够通过操作系统实验的实践过程来加强对理论概念的理解,通过理论概念来进一步指导操作系统实验的实现与改进。

在你开始阅读与实践本书讲解的内容之前,你需要决定用什么编程语言来完成操作系统实验。你可以选择你喜欢的编程语言和你喜欢的CPU上来实现操作系统。我们推荐的编程语言是 Rust ,我们推荐的架构是 RISC-V。

Expand Down
6 changes: 3 additions & 3 deletions source/chapter0/3os-hw-abstract.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
chyyuu:我觉得需要给出执行环境(EE),Task,...,上下文(函数,trap,task,进程...),执行流等的描述。
并且有一个图,展示这些概念的关系。这些概念能够有链接,指向进一步实际定义或使用的地方。
接下来读者可站在操作系统实现的角度来看操作系统。操作系统为了能够更好地管理计算机系统并为应用程序提供便捷的服务,在计算机和操作系统的技术研究和发展的过程中,形成了一系列的核心概念,奠定了操作系统内核设计与实现的基础。
接下来同学可站在操作系统实现的角度来看操作系统。操作系统为了能够更好地管理计算机系统并为应用程序提供便捷的服务,在计算机和操作系统的技术研究和发展的过程中,形成了一系列的核心概念,奠定了操作系统内核设计与实现的基础。

.. note::

在本书中,下面的抽象表示不会仅仅就是一个文字的描述,还会在后续章节对具体操作系统设计与运行的讲述中,以具体化的静态数据结构,动态执行对物理/虚拟资源的变化来展示。从而让读者能够建立操作系统抽象概念与操作系统具体实验之间的内在联系
在本书中,下面的抽象表示不会仅仅就是一个文字的描述,还会在后续章节对具体操作系统设计与运行的讲述中,以具体化的静态数据结构,动态执行对物理/虚拟资源的变化来展示。从而让同学能够建立操作系统抽象概念与操作系统具体实验之间的内在联系

执行环境
----------------------------------------
Expand Down Expand Up @@ -155,7 +155,7 @@
操作系统内核中去执行。

在RISC-V的特权级规范文档中,“陷入” 包含中断和异常,而原来意义上的陷入(trap,系统调用)只是exception中的一种情况。另外还有一种 “软件中断” ,它是指软件可以通过写特定寄存器(mip/sip)的特定位(MSIP/SSIP/USIP)来产生的中断。而异常和中断有严格的区分,在记录产生的异常或中断类型的特定寄存器(mcause/scause)中,寄存器最高位为 ``0`` 表示异常,最高位为 ``1`` 表示中断。进一步的详细信息可以可参考RISC-V的特权级规范文档和后面的章节。
这些都是从不同的视角来阐释中断、陷入和异常,并没有一个唯一精确的解释。对于读者而言,重点是了解这些术语在后续章节的操作系统设计实现中所表示的具体含义和特征。
这些都是从不同的视角来阐释中断、陷入和异常,并没有一个唯一精确的解释。对于同学而言,重点是了解这些术语在后续章节的操作系统设计实现中所表示的具体含义和特征。

.. _term_process:

Expand Down
4 changes: 2 additions & 2 deletions source/chapter1/0intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@
本章代码导读
-----------------------------------------------------

操作系统虽然是软件,但它不是常规的应用软件,需要运行在没有操作系统的裸机环境中。如果采用通常编程方法和编译手段,无法开发出操作系统。其中一个重要的原因编译器编译出的应用软件在缺省情况下是要链接标准库(Rust 编译器和 C 编译器都是这样的),而标准库是依赖于操作系统(如 Linux、Windows 等)的。所以,本章主要是让读者能够脱离常规应用软件开发的思路,理解如何开发没有操作系统支持的操作系统内核。
操作系统虽然是软件,但它不是常规的应用软件,需要运行在没有操作系统的裸机环境中。如果采用通常编程方法和编译手段,无法开发出操作系统。其中一个重要的原因编译器编译出的应用软件在缺省情况下是要链接标准库(Rust 编译器和 C 编译器都是这样的),而标准库是依赖于操作系统(如 Linux、Windows 等)的。所以,本章主要是让同学能够脱离常规应用软件开发的思路,理解如何开发没有操作系统支持的操作系统内核。

为了做到这一步,首先需要写出不需要标准库的软件并通过编译。为此,先把一般应用所需要的标准库的组件给去掉,这会导致编译失败。然后再逐步添加不需要操作系统的极少的运行时支持代码,让编译器能够正常编译出不需要标准库的正常程序。但此时的程序没有显示输出,更没有输入等,但可以正常通过编译,这样就为进一步扩展程序内容打下了一个 **可正常编译OS** 的前期基础。具体可看 :ref:`移除标准库依赖 <term-remove-std>` 一节的内容。

操作系统代码无法像应用软件那样,可以有方便的调试(Debug)功能。这是因为应用之所以能够被调试,也是由于操作系统提供了方便的调试相关的系统调用。而我们不得不再次认识到,需要运行在没有操作系统的裸机环境中,当然没法采用依赖操作系统的传统调试方法了。所以,我们只能采用 ``print`` 这种原始且有效的调试方法。这样,第二步就是让脱离了标准库的软件有输出,这样,我们就能看到程序的运行情况了。为了简单起见,我们可以先在用户态尝试构建没有标准库的支持显示输出的最小运行时执行环境,比较特别的地方在于如何写内嵌汇编完成简单的系统调用。具体可看 :ref:`构建用户态执行环境 <term-print-userminienv>` 一节的内容。

接下来就是尝试构建可在裸机上支持显示的最小运行时执行环境。相对于用户态执行环境,读者需要能够做更多的事情,比如如何关机,如何配置软件运行所在的物理内存空间,特别是栈空间,如何清除 ``bss`` 段,如何通过 ``RustSBI`` 的 ``SBI_CONSOLE_PUTCHAR`` 接口简洁地实现信息输出。这里比较特别的地方是需要了解 ``linker.ld`` 文件中对OS的代码和数据所在地址空间布局的描述,以及基于RISC-V 64的汇编代码 ``entry.asm`` 如何进行栈的设置和初始化,以及如何跳转到Rust语言编写 ``rust_main`` 主函数中,并开始内核最小运行时执行环境的运行。具体可看 :ref:`构建裸机执行环境 <term-print-kernelminienv>` 一节的内容。
接下来就是尝试构建可在裸机上支持显示的最小运行时执行环境。相对于用户态执行环境,同学需要能够做更多的事情,比如如何关机,如何配置软件运行所在的物理内存空间,特别是栈空间,如何清除 ``bss`` 段,如何通过 ``RustSBI`` 的 ``SBI_CONSOLE_PUTCHAR`` 接口简洁地实现信息输出。这里比较特别的地方是需要了解 ``linker.ld`` 文件中对OS的代码和数据所在地址空间布局的描述,以及基于RISC-V 64的汇编代码 ``entry.asm`` 如何进行栈的设置和初始化,以及如何跳转到Rust语言编写 ``rust_main`` 主函数中,并开始内核最小运行时执行环境的运行。具体可看 :ref:`构建裸机执行环境 <term-print-kernelminienv>` 一节的内容。
2 changes: 1 addition & 1 deletion source/chapter1/1app-ee-platform.rst
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ linux-gnu 系统调用支持的版本 ``riscv64gc-unknown-linux-gnu``,是因
- F/D 拓展:提供单/双精度浮点数运算支持。
- C 拓展:提供压缩指令拓展。

G 拓展是基本整数指令集 I 再加上标准指令集拓展 MAFD 的总称,因此 riscv64gc 也就等同于 riscv64imafdc。我们剩下的内容都基于该处理器架构完成。除此之外 RISC-V 架构还有很多标准指令集拓展,有一些还在持续更新中尚未稳定,有兴趣的读者可以浏览最新版的 RISC-V 指令集规范。
G 拓展是基本整数指令集 I 再加上标准指令集拓展 MAFD 的总称,因此 riscv64gc 也就等同于 riscv64imafdc。我们剩下的内容都基于该处理器架构完成。除此之外 RISC-V 架构还有很多标准指令集拓展,有一些还在持续更新中尚未稳定,有兴趣的同学可以浏览最新版的 RISC-V 指令集规范。

Rust 标准库与核心库
----------------------------------
Expand Down
2 changes: 1 addition & 1 deletion source/chapter2/1rv-privilege.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ RISC-V 架构中一共定义了 4 种特权级:

回顾第一章,当时只是实现了简单的支持单个裸机应用的库级别的“三叶虫”操作系统,它和应用程序全程运行在 S 模式下,应用程序很容易破坏没有任何保护的执行环境--操作系统。而在后续的章节中,我们会涉及到RISC-V的 M/S/U 三种特权级:其中应用程序和用户态支持库运行在 U 模式的最低特权级;操作系统内核运行在 S 模式特权级(在本章表现为一个简单的批处理系统),形成支撑应用程序和用户态支持库的执行环境;而第一章提到的预编译的 bootloader -- ``RustSBI`` 实际上是运行在更底层的 M 模式特权级下的软件,是操作系统内核的执行环境。整个软件系统就由这三层运行在不同特权级下的不同软件组成。

在特权级相关机制方面,本书正文中我们重点关心RISC-V的 S/U 特权级, M 特权级的机制细节则是作为可选内容在 :doc:`/appendix-c/index` 中讲解,有兴趣的读者可以参考
在特权级相关机制方面,本书正文中我们重点关心RISC-V的 S/U 特权级, M 特权级的机制细节则是作为可选内容在 :doc:`/appendix-c/index` 中讲解,有兴趣的同学可以参考

.. _term-ecf:
.. _term-trap:
Expand Down
2 changes: 1 addition & 1 deletion source/chapter2/2application.rst
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ Rust 中的 ``asm!`` 宏的完整格式如下:
第 10 行用于告知编译器将我们在程序中给出的嵌入汇编代码保持原样放到最终构建的可执行文件中。如果不这样做的话,编译器可能会把它和其他代码
一视同仁并放在一起进行一些我们期望之外的优化。为了保证语义的正确性,一些比较关键的汇编代码需要加上该选项。

上面这一段汇编代码的含义和内容与第一章中的 :ref:`第一章中U-Mode应用程序中的系统调用汇编代码 <term-llvm-syscall>` 的是一致的,且与 :ref:`第一章中的RustSBI输出到屏幕的SBI调用汇编代码 <term-llvm-sbicall>` 涉及的汇编指令一样,但传递参数的寄存器的含义是不同的。有兴趣的读者可以回顾第一章的 ``console.rs`` 和 ``sbi.rs`` 。
上面这一段汇编代码的含义和内容与第一章中的 :ref:`第一章中U-Mode应用程序中的系统调用汇编代码 <term-llvm-syscall>` 的是一致的,且与 :ref:`第一章中的RustSBI输出到屏幕的SBI调用汇编代码 <term-llvm-sbicall>` 涉及的汇编指令一样,但传递参数的寄存器的含义是不同的。有兴趣的同学可以回顾第一章的 ``console.rs`` 和 ``sbi.rs`` 。

.. note::

Expand Down
2 changes: 1 addition & 1 deletion source/chapter2/3batch-system.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
程序的起始地址,最后一个元素放置最后一个应用程序的结束位置。这样每个应用程序的位置都能从该数组中相邻两个元素中得知。这个数组所在的位置
同样也由全局符号 ``_num_app`` 所指示。

这个文件是在 ``cargo build`` 的时候,由脚本 ``os/build.rs`` 控制生成的。有兴趣的读者可以参考其代码
这个文件是在 ``cargo build`` 的时候,由脚本 ``os/build.rs`` 控制生成的。有兴趣的同学可以参考其代码

找到并加载应用程序二进制码
-----------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions source/chapter2/4trap-handling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ CSR,比如 CPU 所在的特权级。我们要保证它们的变化在我们的

当 MODE 字段为 0 的时候, ``stvec`` 被设置为 Direct 模式,此时进入 S 模式的 Trap 无论原因如何,处理 Trap 的入口地址都是 ``BASE<<2``
, CPU 会跳转到这个地方进行异常处理。本书中我们只会将 ``stvec`` 设置为 Direct 模式。而 ``stvec`` 还可以被设置为 Vectored 模式,
有兴趣的读者可以自行参考 RISC-V 指令集特权级规范。
有兴趣的同学可以自行参考 RISC-V 指令集特权级规范。

而当 CPU 完成 Trap 处理准备返回的时候,需要通过一条 S 特权级的特权指令 ``sret`` 来完成,这一条指令具体完成以下功能:

Expand Down Expand Up @@ -602,7 +602,7 @@ S 特权级,而它希望能够切换到 U 特权级。在 RISC-V 架构中,

.. note::

有兴趣的读者可以思考: sscratch 是何时被设置为内核栈顶的?
有兴趣的同学可以思考: sscratch 是何时被设置为内核栈顶的?



Expand Down
4 changes: 2 additions & 2 deletions source/chapter3/0intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@

.. hint::

读者也许会有疑问:由于只有一个 处理器,即使这样做,同一时间最多还是只能运行一个应用,还浪费了更多的内存来把所有
同学也许会有疑问:由于只有一个 处理器,即使这样做,同一时间最多还是只能运行一个应用,还浪费了更多的内存来把所有
的应用都加载进来。那么这样做有什么意义呢?

读者可以带着这个问题继续看下去。后面我们会介绍这样做到底能够解决什么问题。
同学可以带着这个问题继续看下去。后面我们会介绍这样做到底能够解决什么问题。

实践体验
-------------------------------------
Expand Down
Loading

0 comments on commit 4fb6ebe

Please sign in to comment.