一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情。
地址转换
之前学习过的limited direct execution可以简单理解为操作系统通过一系列机制限制用户进程进行任何“不正确”的操作,现在再提出一个对于内存的虚拟化有类似功能的机制:address translation。
通过address translation,操作系统可以将进程的每一个内存访问地址从地址空间,转换为实际存在的物理内存地址。
提供这样一种地址转换机制有两大意义,一是以此方式为进程提供一个可以随意分配的空间,方便程序的开发;二是为进程之间的运行和进程与操作系统之间的运行提供内存保护,任何一个进程都不能随意访问另一个进程的地址空间。
在实际讲解之前,我们先通过一个例子来建立一个简单的内存模型,下图是一个简单的C代码和它翻译出来的机器代码
它的代码(指令)存储在它自身的地址空间中,而它的地址空间存储在物理内存空间中一块。
一边理解这个模型,同时我们会以一种和CPU虚拟化类似的过程来设计出一个高效、可控、灵活的地址转换机制。
不管什么时候,高效和控制一直是操作系统主要的目标,高效表示我们需要设计合适的算法、并且借助硬件的帮助。控制意味着系统不能允许不合理的内存访问。灵活表示在上面两个前提下,进程可以自由的访问它的地址空间中的任何内存。
类似的,为了简化模型,本次我们所学的机制都基于这几个关键的假设:
1.地址空间在物理内存上是连续的 2.地址空间不会很大 3.地址空间都一样大
一开始的地址转换非常简单(只用了几个寄存器),你应该也能猜到,就是存储一些变量。具体来说,就是两个寄存器:基寄存器和边界寄存器(原本叫base-bounds或者称为dynamic-relocation),是一种基于硬件的地址转换机制,每一个CPU都含有一对base register和bound register。其中base register负责将进程中的每一次内存访问进行偏移(相加)到实际的物理地址上,bound register负责查看进程的每一次内存访问是否在其所分配的地址空间内。
如果超出空间,则触发trap,由操作系统按照exception程序来进行处理错误进程。
每一个CPU都有一个基寄存器,当CPU要切换进程,就会由OS加载它的基地址到寄存器上
基于硬件的address translation十分高效稳定,但是无法利用到进程地址空间中栈和堆栈之间被分配但未使用的大量空间,也被称为internal fragmentation即内存碎片,这也是接下base-bounds要改良的方向
曾经出现过纯基于软件的地址转换,但是不仅低效,而且不能提供操作系统需要的保护。
至此,我们已经学习了不少在操作系统中由硬件支持的底层机制,我们可以将机器开机和简单进程运行时的各种过程抽象为下图
图中包含了许多我们学过的硬件机制:trap table、interrupt time、base-bound registers、switch context、kernel/user mode。还有许多操作系统的底层功能:各种硬件可触发的system call如time、exception等,存储进程状态和内存空间状态的process table、free list。