提交 7353f0fd 编写于 作者: chyyuu1972's avatar chyyuu1972

update ch4:sec1/2/3

上级 f7dfb8bc
......@@ -259,6 +259,8 @@ RAII 的含义是说,将一个使用前必须获取的资源的生命周期绑
最后,让我们尝试一下动态内存分配吧!
.. chyyuu 如何尝试???
.. code-block:: rust
:linenos:
......
......@@ -38,10 +38,10 @@
就可以同时把多个应用的数据驻留在内存中。在任务切换的时候只需完成任务上下文保存与恢复即可,这只是在内存的帮助下保存、
恢复少量通用寄存器,甚至无需访问外存,这从很大程度上降低了任务切换的开销。
在本章的引言中介绍过第三章的做法有哪些问题。对于应用来说,它需要自己决定会被加载到哪个物理地址运行,直接访问真实的
物理内存,这需要开发者对于硬件的特性和使用方法有更多了解,产生额外的学习成本,也会为应用的开发和调试带来不便。从
内核的角度来看,将直接访问物理内存的权力下放到应用会使得它难以对应用的访存行为进行有效管理,已有的特权级机制亦无法
阻止很多来自应用的恶意行为。
在本章的引言中介绍过第三章中操作系统的做法对应用程序开发带了一定的困难。从应用开发的角度看,需要应用程序决定自己会被加载到哪个物理地址运行,需要直接访问真实的
物理内存。这就要求应用开发者对于硬件的特性和使用方法有更多了解,产生额外的学习成本,也会为应用的开发和调试带来不便。从
内核的角度来看,将直接访问物理内存的权力下放到应用会使得它难以对应用程序的访存行为进行有效管理,已有的特权级机制亦无法
阻止很多来自应用程序的恶意行为。
加一层抽象加强内存管理
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
......@@ -57,18 +57,17 @@
.. _term-address-space:
.. _term-virtual-address:
最终,到目前为止仍被内核广泛使用的抽象被称为 **地址空间** (Address Space) 。某种程度上讲,可以将它看成一块
最终,到目前为止仍被操作系统内核广泛使用的抽象被称为 **地址空间** (Address Space) 。某种程度上讲,可以将它看成一块
巨大但并不一定真实存在的内存。在每个应用程序的视角里,操作系统分配给应用程序一个范围有限(但其实很大),独占的连续地址空间(其中有些地方被操作系统限制不能访问,如内核本身占用的虚地址空间等),因此应用程序可以在划分给它的地址空间中随意规划内存布局,它的
各个段也就可以分别放置在地址空间中它希望的位置(当然是操作系统允许应用访问的地址)。应用同样可以使用一个地址作为索引来读写自己地址空间的数据,就像用物理地址
作为索引来读写物理内存上的数据一样。这种地址被称为 **虚拟地址** (Virtual Address) 。
作为索引来读写物理内存上的数据一样。这种地址被称为 **虚拟地址** (Virtual Address) 。当然,操作系统要达到 **地址空间** 抽象的设计目标,需要有计算机硬件的支持,这就是计算机组成原理课上讲到的 ``MMU`` 和 ``TLB`` 等硬件机制。
从此,应用能够直接看到并访问的就只有地址空间,且它的任何一次访存使用的都是虚拟地址,无论取指令来执行还是读写
栈、堆或是全局数据段都是如此。事实上,特权级机制被拓展,使得应用不再具有通过物理地址直接访问物理内存的能力。
从此,应用能够直接看到并访问的内存就只有操作系统提供的地址空间,且它的任何一次访存使用的地址都是虚拟地址,无论取指令来执行还是读写
栈、堆或是全局数据段都是如此。事实上,特权级机制被拓展,使得应用不再具有通过物理地址直接访问物理内存的能力。应用所处的执行环境在安全方面被进一步强化,形成了用户态特权级和地址空间的二维安全措施。
由于每个应用独占一个地址空间,里面只含有自己的各个段,于是它可以随意规划
各个段的分布而无需考虑和其他应用冲突;同时,它完全无法窃取或者破坏其他应用的数据,毕竟那些段在其他应用的地址空间
内,鉴于应用只能通过虚拟地址读写它自己的地址空间,这是它没有能力去访问的。这样看来这个抽象有一定安全性,并为系统
提供了部分稳定性。
内,鉴于应用只能通过虚拟地址读写它自己的地址空间,这是它没有能力去访问的。这是 **地址空间** 抽象对应用程序执行的安全性和稳定性的一种保障。
.. image:: address-translation.png
......@@ -76,13 +75,13 @@
.. _term-address-translation:
我们知道应用的数据终归还是存在物理内存中的,那么虚拟地址如何形成地址空间,虚拟地址空间如何转换为物理内存呢?操作系统可以设计巧妙的数据结构来表示地址空间。但如果完全由操作系统来完成转换每次处理器地址访问所需的虚实地址转换,那开销就太大了。这就需要扩展硬件功能来加速地址转换过程(回忆 ** 计算机组成原理** 课上讲的 ``MMU`` )。
我们知道应用的数据终归还是存在物理内存中的,那么虚拟地址如何形成地址空间,虚拟地址空间如何转换为物理内存呢?操作系统可以设计巧妙的数据结构来表示地址空间。但如果完全由操作系统来完成转换每次处理器地址访问所需的虚实地址转换,那开销就太大了。这就需要扩展硬件功能来加速地址转换过程(回忆 ** 计算机组成原理** 课上讲的 ``MMU`` 和 ``TLB`` )。
增加硬件加速虚实地址转换
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如上图所示,当应用取指或者执行
开始回顾一下 ** 计算机组成原理** 课。如上图所示,当应用取指或者执行
一条访存指令的时候,它都是在以虚拟地址为索引读写自己的地址空间。此时,CPU 中的 **内存管理单元**
(MMU, Memory Management Unit) 自动将这个虚拟地址进行 **地址转换** (Address Translation) 变为一个物理地址,
也就是物理内存上这个应用的数据真实被存放的位置。也就是说,在 MMU 的帮助下,应用对自己地址空间的读写才能被实际转化为
......@@ -96,9 +95,9 @@
回过头来,在介绍内核对于 CPU 资源的抽象——时分复用的时候,我们曾经提到它为应用制造了一种每个应用独占整个 CPU 的
幻象,而隐藏了多个应用分时共享 CPU 的实质。而地址空间也是如此,应用只需、也只能看到它独占整个地址空间的幻象,而
藏在背后的实质仍然是多个应用共享内存,它们的数据分别存放在内存的不同位置。
藏在背后的实质仍然是多个应用共享物理内存,它们的数据分别存放在内存的不同位置。
地址空间只是一层抽象接口,它有很多种具体的实现策略。对于不同的实现策略来说,内核如何规划应用数据放在物理内存的位置,
地址空间只是一层抽象接口,它有很多种具体的实现策略。对于不同的实现策略来说,操作系统内核如何规划应用数据放在物理内存的位置,
而 MMU 又如何进行地址转换也都是不同的。下面我们简要介绍几种曾经被使用的策略,并探讨它们的优劣。
分段内存管理
......@@ -151,14 +150,15 @@ MMU 需要用一对不同的 :math:`\text{base/bound}` 进行区分。这里由
尽管内碎片被消除了,但内存浪费问题并没有完全解决。这是因为每个段的大小都是不同的(它们可能来自不同的应用,功能
也不同),内核就需要使用更加通用、也更加复杂的连续内存分配算法来进行内存管理,而不能像之前的插槽那样以一个比特
为单位。顾名思义,连续内存分配算法就是每次需要分配一块连续内存来存放一个段的数据。
随着一段时间的分配和回收,物理内存还剩下一些可用的连续块,其中有一些只是很小的间隙,它们自己已经无法被
随着一段时间的分配和回收,物理内存还剩下一些相互不连续的较小的可用连续块,其中有一些只是两个已分配内存块之间的很小的间隙,它们自己可能由于空间较小,已经无法被
用于分配,被称为 **外碎片** (External Fragment) 。
如果这时再想分配一个比较大的块或者越过间隙增长一个段的大小,
就需要将这些外碎片“拼起来”。然而这是一件开销很大的事情,这需要移动一些已有的段在物理内存上的位置让它们
连续分布,从而它们中间的间隙就可以被释放出来用于分配。这个过程同样涉及到极大的内存读写开销。如果连续内存分配算法
如果这时再想分配一个比较大的块,
就需要将这些不连续的外碎片“拼起来”,形成一个大的连续块。然而这是一件开销很大的事情,涉及到极大的内存读写开销。具体而言,这需要移动和调整一些已分配内存块在物理内存上的位置,才能让那些小的外碎片能够合在一起,形成一个大的空闲块。如果连续内存分配算法
选取得当,可以尽可能减少这种操作。课上所讲到的那些算法,包括 first-fit/worst-fit/best-fit 或是 buddy
system,其具体表现取决于实际的应用需求,各有优劣。那么,分段内存管理带来的外碎片和连续内存分配算法比较复杂的
system,其具体表现取决于实际的应用需求,各有优劣。
那么,分段内存管理带来的外碎片和连续内存分配算法比较复杂的
问题可否被解决呢?
分页内存管理
......
......@@ -12,13 +12,19 @@
虚拟地址和物理地址
------------------------------------------------------
内存控制的CSR寄存器
内存控制相关的CSR寄存器
^^^^^^^^^^^^^^^^^^^^
默认情况下 MMU 未被使能,此时无论 CPU 位于哪个特权级,访存的地址都会作为一个物理地址交给对应的内存控制单元来直接
访问物理内存。我们可以通过修改 S 特权级的一个名为 ``satp`` 的 CSR 来启用分页模式,在这之后 S 和 U 特权级的访存
地址会被视为一个虚拟地址,它需要经过 MMU 的地址转换变为一个物理地址,再通过它来访问物理内存;而 M 特权级的访存地址
被视为一个物理地址还是一个需要经历和 S/U 特权级相同的地址转换的虚拟地址则取决于配置,在这里我们并不深入。
地址会被视为一个虚拟地址,它需要经过 MMU 的地址转换变为一个物理地址,再通过它来访问物理内存;而 M 特权级的访存地址,我们可设定是内存的物理地址。
.. note::
M 特权级的访存地址被视为一个物理地址还是一个需要经历和 S/U 特权级相同的地址转换的虚拟地址取决于硬件配置,在这里我们不会进一步探讨。
.. chyyuu M模式下,应该访问的是物理地址???
.. image:: satp.png
:name: satp-layout
......@@ -49,7 +55,7 @@
属于哪一个虚拟页面/物理页帧。
地址转换是以页为单位进行的,在地址转换的前后地址的页内偏移部分不变。可以认为 MMU 只是从虚拟地址中取出 27 位虚拟页号,
在页表中查到其对应的物理页号(如果存在的话),最后将得到的物理页号与虚拟地址的页内偏移依序拼接到一起就变成了物理地址。
在页表中查到其对应的物理页号(如果存在的话),最后将得到的44位的物理页号与虚拟地址的12位页内偏移依序拼接到一起就变成了56位的物理地址。
.. _high-and-low-256gib:
......@@ -57,14 +63,14 @@
**RV64 架构中虚拟地址为何只有 39 位?**
在 64 位架构上虚拟地址长度确实应该和位宽一致为 64 位,但是在启用 SV39 分页模式下,只有 39 位是真正有意义的。
在 64 位架构上虚拟地址长度确实应该和位宽一致为 64 位,但是在启用 SV39 分页模式下,只有 39 位是真正有意义的。
SV39 分页模式规定 64 位虚拟地址的 :math:`[63:39]` 这 25 位必须和第 38 位相同,否则 MMU 会直接认定它是一个
不合法的虚拟地址。通过这个检查之后 MMU 再取出 39 位尝试将其转化为一个 56 位的物理地址。
不合法的虚拟地址。通过这个检查之后 MMU 再取出 39 位尝试将其转化为一个 56 位的物理地址。
也就是说,所有 :math:`2^{64}` 个虚拟地址中,只有最低的 :math:`256\text{GiB}` (当第 38 位为 0 时)
以及最高的 :math:`256\text{GiB}` (当第 38 位为 1 时)是可能通过 MMU 检查的。当我们写软件代码的时候,一个
地址的位宽毋庸置疑就是 64 位,我们要清楚可用的只有最高和最低这两部分,尽管它们已经巨大的超乎想象了;而本节中
我们专注于介绍 MMU 的机制,强调 MMU 看到的真正用来地址转换的虚拟地址,这只有 39 位。
我们专注于介绍 MMU 的机制,强调 MMU 看到的真正用来地址转换的虚拟地址只有 39 位。
......@@ -315,7 +321,7 @@ usize 的一种简单包装。我们刻意将它们各自抽象出来而不是
有意义并能在页表中查到实际的物理页号的虚拟页号在 :math:`2^{27}` 中也只是很小的一部分。由此线性表的绝大部分空间
其实都是被浪费掉的。
那么如何进行优化呢?核心思想就在于按需分配,也就是说:有多少合法的虚拟页号,我们就维护一个多大的映射,并为此使用
那么如何进行优化呢?核心思想就在于 **按需分配** ,也就是说:有多少合法的虚拟页号,我们就维护一个多大的映射,并为此使用
多大的内存用来保存映射。这是因为,每个应用的地址空间最开始都是空的,或者说所有的虚拟页号均不合法,那么这样的页表
自然不需要占用任何内存, MMU 在地址转换的时候无需关心页表的内容而是将所有的虚拟页号均判为不合法即可。而在后面,
内核已经决定好了一个应用的各逻辑段存放位置之后,它就需要负责从零开始以虚拟页面为单位来让该应用的地址空间的某些部分
......@@ -367,8 +373,11 @@ usize 的一种简单包装。我们刻意将它们各自抽象出来而不是
非叶节点的页表项标志位含义和叶节点相比有一些不同:
- 当 V 为 0 的时候,代表当前字符指针是一个空指针,无法走向下一级节点;
- 只有当 R/W/X 均为 0 的时候才能向下走。在这里我们给出 SV39 中的 R/W/X 组合的含义:
- 当 V 为 0 的时候,代表当前指针是一个空指针,无法走向下一级节点,即该页表项对应的虚拟地址范围是无效的;
- 只有当V 为1 且 R/W/X 均为 0 时,表示是一个合法的页目录表项,其包含的指针会指向下一级的页表。
- 注意: 当V 为1 且 R/W/X 不全为 0 时,表示是一个合法的页表项,其包含了虚地址对应的物理页号。
在这里我们给出 SV39 中的 R/W/X 组合的含义:
.. image:: pte-rwx.png
:align: center
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册