0intro.rst 11.0 KB
Newer Older
Y
Yifan Wu 已提交
1 2 3
引言
==============================

Y
Yifan Wu 已提交
4
本章导读
chyyuu1972's avatar
chyyuu1972 已提交
5
-------------------------------
Y
Yifan Wu 已提交
6

chyyuu1972's avatar
chyyuu1972 已提交
7 8 9
..
  chyyuu:有一个ascii图,画出我们做的OS。

chyyuu1972's avatar
chyyuu1972 已提交
10 11 12 13 14 15 16 17

本章展现了操作系统一系列功能:

- 通过动态内存分配,提高了应用程序对内存的动态使用效率
- 通过页表的虚实内存映射机制,简化了编译器对应用的地址空间设置
- 通过页表的虚实内存映射机制,加强了应用之间,应用与内核之间的内存隔离,增强了系统安全
- 通过页表的虚实内存映射机制,可以实现空分复用(提出,但没有实现)

Y
Yifan Wu 已提交
18 19 20
.. _term-illusion:
.. _term-time-division-multiplexing:
.. _term-transparent:
chyyuu1972's avatar
chyyuu1972 已提交
21

22
上一章,我们分别实现了多道程序和分时多任务系统,它们的核心机制都是任务切换。由于它们的设计初衷不同,它们切换的时机和策略也不同。有趣的一点是,任务切换机制对于应用是完全 **透明** (Transparent) 的,应用可以不对内核实现该机制的策略做任何假定(除非要进行某些针对性优化),甚至可以完全不知道这机制的存在。在大多数应用(也就是应用开发者)的视角中,它们会独占一整个 CPU 直到执行完毕。当然,通过上一章的学习,我们知道在现代操作系统中,出于公平性的考虑,我们极少会让这种情况发生。所以应用自认为的独占只是内核想让应用看到的一种 **幻象** (Illusion) ,而 CPU 计算资源被 **时分复用** (TDM, Time-Division Multiplexing) 的实质被内核通过恰当的抽象隐藏了起来,对应用不可见。
chyyuu1972's avatar
chyyuu1972 已提交
23

24
与之相对,我们目前还没有对内存管理功能进行有效的管理,仅仅是把程序放到某处的物理内存中。在上一章中,出于任务切换的需要,所有的应用都在初始化阶段被加载到内存中并同时驻留下去直到它们全部运行结束。而且,所有的应用都直接通过物理地址访问物理内存。这会带来以下问题:
Y
Yifan Wu 已提交
25

26 27 28
- 首先,内核提供给应用的内存访问接口不够透明,也不好用。由于应用直接访问物理内存,这需要它在构建的时候就需要规划自己需要被加载到哪个地址运行。为了避免冲突可能还需要应用的开发者们对此进行协商,这显然是一件在今天看来不可理喻且极端麻烦的事情。
- 其次,内核并没有对应用的访存行为进行任何保护措施,每个应用都有整块物理内存的读写权力。即使应用被限制在 U 特权级下运行,它还是能够造成很多麻烦:比如它可以读写其他应用的数据来窃取信息或者破坏它的正常运行;甚至它还可以修改内核的代码段来替换掉原本的 ``trap_handler`` 来挟持内核执行恶意代码。总之,这造成系统既不安全、也不稳定。
- 再次,目前应用的内存使用空间在其运行前已经限定死了,内核不能灵活地给应用程序提供的运行时动态可用内存空间。比如一个应用结束后,这个应用所占的空间就被释放了,但这块空间无法动态地给其它还在运行的应用使用。
chyyuu1972's avatar
chyyuu1972 已提交
29

30
因此,为了防止应用胡作非为,本章将更好的管理物理内存,并提供给应用一个抽象出来的更加透明易用、也更加安全的访存接口,就和上一章我们对 CPU 资源所做的事情一样,这就是我们要设计实现的具有超强防护能力的侏罗纪“头甲龙”操作系统。 并可归纳抽象出地址空间,虚拟地址等操作系统的概念。
chyyuu1972's avatar
chyyuu1972 已提交
31

32
而对于灵活使用动态内存空间的问题,将在后续章节中进一步描述。
chyyuu1972's avatar
chyyuu1972 已提交
33 34 35

..
  chyyuu:在哪里讲解虚存的设计与实现???
Y
Yifan Wu 已提交
36 37


Y
Yifan Wu 已提交
38
实践体验
chyyuu1972's avatar
chyyuu1972 已提交
39
-----------------------
Y
Yifan Wu 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

本章的应用和上一章相同,只不过由于内核提供给应用的访存接口被替换,应用的构建方式发生了变化,这方面在下面会深入介绍。
因此应用运行起来的话效果是和上一章保持一致的。

获取本章代码:

.. code-block:: console

   $ git clone https://github.com/rcore-os/rCore-Tutorial-v3.git
   $ cd rCore-Tutorial-v3
   $ git checkout ch4

在 qemu 模拟器上运行本章代码:

.. code-block:: console

   $ cd os
   $ make run

Y
Yifan Wu 已提交
59
将 Maix 系列开发板连接到 PC,并在上面运行本章代码:
Y
Yifan Wu 已提交
60 61 62 63 64 65 66 67 68 69

.. code-block:: console

   $ cd os
   $ make run BOARD=k210

如果顺利的话,我们将看到和上一章相同的运行结果(以 K210 平台为例):

.. code-block::

Y
Yifan Wu 已提交
70
   [rustsbi] RustSBI version 0.1.1
Y
Yifan Wu 已提交
71 72 73 74 75 76 77
   .______       __    __      _______.___________.  _______..______   __
   |   _  \     |  |  |  |    /       |           | /       ||   _  \ |  |
   |  |_)  |    |  |  |  |   |   (----`---|  |----`|   (----`|  |_)  ||  |
   |      /     |  |  |  |    \   \       |  |      \   \    |   _  < |  |
   |  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
   | _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|

Y
Yifan Wu 已提交
78
   [rustsbi] Platform: K210 (Version 0.1.0)
Y
Yifan Wu 已提交
79
   [rustsbi] misa: RV64ACDFIMSU
Y
Yifan Wu 已提交
80
   [rustsbi] mideleg: 0x22
Y
Yifan Wu 已提交
81 82 83 84 85
   [rustsbi] medeleg: 0x1ab
   [rustsbi] Kernel entry: 0x80020000
   [kernel] Hello, world!
   .text [0x80020000, 0x8002b000)
   .rodata [0x8002b000, 0x8002e000)
Y
Yifan Wu 已提交
86 87
   .data [0x8002e000, 0x8004c000)
   .bss [0x8004c000, 0x8035d000)
Y
Yifan Wu 已提交
88 89 90 91 92 93 94 95 96
   mapping .text section
   mapping .rodata section
   mapping .data section
   mapping .bss section
   mapping physical memory
   [kernel] back to world!
   remap_test passed!
   init TASK_MANAGER
   num_app = 4
Y
Yifan Wu 已提交
97
   power_3 [10000/300000power_5 [10000/210000]
Y
Yifan Wu 已提交
98 99
   power_5 [20000/210000]
   power_5 [30000/210000]
Y
Yifan Wu 已提交
100
   power_7 [10000/240000]
Y
Yifan Wu 已提交
101 102
   power_7 [20000/240000]
   power_7 [30000/240000]
Y
Yifan Wu 已提交
103 104 105
   ]
   power_3 [20000/300000]
   power_3 [30000/300000]
Y
Yifan Wu 已提交
106
   power_3 [40000/300000]
Y
Yifan Wu 已提交
107 108 109 110 111 112
   power_5 [40000/210000]
   power_5 [50000/210000]
   power_5 [60000/210000]
   power_7 [40000/240000]
   power_7 [50000/240000]
   power_7 [60000/240000]
Y
Yifan Wu 已提交
113 114 115 116 117 118 119 120 121 122 123 124
   power_3 [50000/300000]
   power_3 [60000/300000]
   power_3 [70000/300000]
   power_5 [70000/210000]
   power_5 [80000/210000]
   power_5 [90000/210000]
   power_7 [70000/240000]
   power_7 [80000/240000]
   power_7 [90000/240000]
   power_3 [80000/300000]
   power_3 [90000/300000]
   power_3 [100000/300000]
Y
Yifan Wu 已提交
125
   power_5 [100000/210000]
Y
Yifan Wu 已提交
126 127 128 129 130
   power_5 [110000/210000]
   power_5 [120000/210000]
   power_7 [100000/240000]
   power_7 [110000/240000]
   power_7 [120000/240000]
Y
Yifan Wu 已提交
131 132 133 134 135 136
   power_3 [110000/300000]
   power_3 [120000/300000]
   power_3 [130000/300000]
   power_5 [130000/210000]
   power_5 [140000/210000]
   power_5 [150000/210000]
Y
Yifan Wu 已提交
137
   power_7 [130000/240000]
Y
Yifan Wu 已提交
138 139
   power_7 [140000/240000]
   power_7 [150000/240000]
Y
Yifan Wu 已提交
140 141 142 143 144 145 146 147 148
   power_3 [140000/300000]
   power_3 [150000/300000]
   power_3 [160000/300000]
   power_5 [160000/210000]
   power_5 [170000/210000]
   power_5 [180000/210000]
   power_7 [160000/240000]
   power_7 [170000/240000]
   power_7 [180000/240000]
Y
Yifan Wu 已提交
149
   power_3 [170000/300000]
Y
Yifan Wu 已提交
150 151
   power_3 [180000/300000]
   power_3 [190000/300000]
Y
Yifan Wu 已提交
152
   power_5 [190000/210000]
Y
Yifan Wu 已提交
153 154
   power_5 [200000/210000]
   power_5 [210000/210000]
Y
Yifan Wu 已提交
155 156 157 158 159 160 161
   5^210000power_7 [190000/240000]
   power_7 [200000/240000]
   power_7 [210000/240000]
   power_3 [200000/300000]
   power_3 [210000/300000]
   power_3 [220000/300000]
   = 527227302(mod 998244353)
Y
Yifan Wu 已提交
162 163 164 165 166 167 168
   Test power_5 OK!
   [kernel] Application exited with code 0
   power_3 [230000/300000]
   power_3 [240000/300000]
   power_3 [250000/300000]
   power_7 [220000/240000]
   power_7 [230000/240000]
Y
Yifan Wu 已提交
169 170
   power_7 [240000/240000]
   7^240000 = 304164893power_3 [260000/300000]
Y
Yifan Wu 已提交
171 172
   power_3 [270000/300000]
   power_3 [280000/300000]
Y
Yifan Wu 已提交
173
   (mod 998244353)
Y
Yifan Wu 已提交
174 175
   Test power_7 OK!
   [kernel] Application exited with code 0
Y
Yifan Wu 已提交
176 177 178
   power_3 [290000/300000]
   power_3 [300000/300000]
   3^300000 = 612461288(mod 998244353)
Y
Yifan Wu 已提交
179 180 181 182 183
   Test power_3 OK!
   [kernel] Application exited with code 0
   Test sleep OK!
   [kernel] Application exited with code 0
   [kernel] Panicked at src/task/mod.rs:112 All applications completed!
Y
Yifan Wu 已提交
184
   [rustsbi] reset triggered! todo: shutdown all harts on k210; program halt. Type: 0, reason: 0
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202

本章代码树
-----------------------------------------------------

.. code-block::
  :linenos:
  :emphasize-lines: 52

  ├── bootloader
  │   ├── rustsbi-k210.bin
  │   └── rustsbi-qemu.bin
  ├── LICENSE
  ├── os
  │   ├── build.rs
  │   ├── Cargo.lock
  │   ├── Cargo.toml
  │   ├── Makefile
  │   └── src
203
  │       ├── config.rs(修改:新增一些内存管理的相关配置)
204 205 206 207
  │       ├── console.rs
  │       ├── entry.asm
  │       ├── lang_items.rs
  │       ├── link_app.S
208 209 210
  │       ├── linker-k210.ld(修改:将跳板页引入内存布局)
  │       ├── linker-qemu.ld(修改:将跳板页引入内存布局)
  │       ├── loader.rs(修改:仅保留获取应用数量和数据的功能)
211
  │       ├── main.rs(修改)
212 213 214 215 216 217 218
  │       ├── mm(新增:内存管理的 mm 子模块)
  │       │   ├── address.rs(物理/虚拟 地址/页号的 Rust 抽象)
  │       │   ├── frame_allocator.rs(物理页帧分配器)
  │       │   ├── heap_allocator.rs(内核动态内存分配器)
  │       │   ├── memory_set.rs(引入地址空间 MemorySet 及逻辑段 MemoryArea 等)
  │       │   ├── mod.rs(定义了 mm 模块初始化方法 init)
  │       │   └── page_table.rs(多级页表抽象 PageTable 以及其他内容)
219 220
  │       ├── sbi.rs
  │       ├── syscall
221
  │       │   ├── fs.rs(修改:基于地址空间的 sys_write 实现)
222 223 224
  │       │   ├── mod.rs
  │       │   └── process.rs
  │       ├── task
225
  │       │   ├── context.rs(修改:构造一个跳转到不同位置的初始任务上下文)
226 227 228 229 230 231
  │       │   ├── mod.rs(修改,详见文档)
  │       │   ├── switch.rs
  │       │   ├── switch.S
  │       │   └── task.rs(修改,详见文档)
  │       ├── timer.rs
  │       └── trap
232 233 234
  │           ├── context.rs(修改:在 Trap 上下文中加入了更多内容)
  │           ├── mod.rs(修改:基于地址空间修改了 Trap 机制,详见文档)
  │           └── trap.S(修改:基于地址空间修改了 Trap 上下文保存与恢复汇编代码)
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
  ├── README.md
  ├── rust-toolchain
  ├── tools
  │   ├── kflash.py
  │   ├── LICENSE
  │   ├── package.json
  │   ├── README.rst
  │   └── setup.py
  └── user
      ├── build.py(移除)
      ├── Cargo.toml
      ├── Makefile
      └── src
          ├── bin
          │   ├── 00power_3.rs
          │   ├── 01power_5.rs
          │   ├── 02power_7.rs
          │   └── 03sleep.rs
          ├── console.rs
          ├── lang_items.rs
          ├── lib.rs
256
          ├── linker.ld(修改:将所有应用放在各自地址空间中固定的位置)
257
          └── syscall.rs