Loading... # 内存虚拟化 ## 1. 动态重定位(base and bound) 基于硬件实现,通过基址寄存器(base)和界限寄存器(bound)。基址寄存器负责地址转换,界限寄存器用于确保这个地址处于进程地址空间范围内(界限检查)。 这种将虚拟地址转换为物理地址的技术,就是所谓的地址转换技术,在这个过程中,硬件取得虚拟地址,然后将他转换为实际的物理地址,这种重定位是运行时发生的,所以被称为动态重定位。 ``` 真实物理地址 = 进程基址 + 进程中的虚拟地址 ``` ![内存重定位][1] ## 2. 分段(segmentation) 若使用动态重定位技术,可以发现,栈与堆之间有大量的空闲空间,如果将这个进程的整个地址空间放入物理内存,那么栈和堆之间的地址虽然没有被进程使用,但依然会占用实际的物理内存。此外,还有另一个问题,当剩余物理内存无法提供连续区域来放置完整的地址空间,显然无法为这个进程开辟独立的地址空间。 因此在动态重定位基础上更进一步的分段技术(同样是基于硬件的),通过使用三个段寄存器,使得虚拟地址空间中的稀疏空间(堆与栈之间的空闲空间)消除。具体原理是增加了对堆、栈、代码区的基址和界限详细描述规范,而不是仅规范了整个进程的基址和界限。通过细化的描述,消除了虚拟地址空间的空闲空间。并且通过对堆、栈、代码区的详细分段,使得进程的真实物理地址不必连续。提高了物理内存的利用率。 现在整个流程是 进程中的虚拟地址 -> 对应的分段的虚拟地址二进制形式(段基址 + 段偏移) -> 真实物理地址 ``` 真实物理地址 = 当前进程下具体某段的基址(段基址) + 当前进程下具体某段的偏移(段偏移) = 当前进程下具体某段的基址 + 虚拟地址 - 虚拟空间中段的偏移量 ``` ![分段][2] | 段 | 段基址 | 大小 | 增长方向 | 二进制代号 | ---- | ------ | ------ | ------ | ----- | 代码 | 32KB | 2KB| 1 | 00 | | 堆 | 34KB | 2KB| 1 | 01 | | 栈 | 28KB | 2KB| 0 | 11 | 注意: 在机器中,16KB虚拟地址的真实传递地址是14位的二进制,其中前两位用于标识段。后12位用于标识段偏移。计算可知,最大段偏移为4KB。 ![虚拟地址的二进制形式][3] ### 堆的虚拟地址-> 虚拟地址的二进制形式 以进程中虚拟地址4200为例,它处于堆区。它的段基址为34KB 从虚拟地址空间堆的虚拟地址偏移量为 4KB 。 真实物理地址 = 34KB + 4200 - 4KB 段偏移 = 4200 - 4KB = 4200 - 4096 = 104 下面计算其 虚拟地址的二进制形式 堆的二进制代号 01 段偏移 104 = 0x 0000 0110 1000 虚拟地址的二进制形式为 0x 01 0000 0110 1000 ### 栈的虚拟地址 ->虚拟地址的二进制形式 进程中的虚拟地址 15KB, 处于栈区。 段基址为28KB。 虚拟地址空间 栈的虚拟地址偏移量为 16KB。 真实物理地址 = 28KB + 15KB - 16KB = 27KB。 段偏移 = -1 KB 下面计算其 虚拟地址的二进制形式 栈的二进制代号 11 段偏移 -1KB 由于段偏移最大为4KB 因此段偏移为 -1KB = 3KB = 0x 1100 0000 0000 虚拟地址的二进制形式为 0x 11 1100 0000 0000 ## 3. 分页 分段可以使得虚拟地址空间内的未分配空间不会占用实际物理内存,但是没法解决实际物理内存的碎片问题,随着越来越多的物理内存未分配空间碎片化。新的程序将面临没有内存分配的尴尬,虽然剩余内存总量是够的,但是它们不连续,无法分配。 于是分页技术诞生了,分页的核心思想是将内存的使用按照固定大小分配,即划定某个固定量大小的内存为基本量,任何栈、堆、代码区的大小都是这个基本量的整数倍,这就是在物理内存中对应的页帧大小。这样做的优点有:方便了物理内存的分配,虚拟地址的栈、堆是连续的,这不意味着物理内存上的堆、栈也要连续,只要找到一定数量的页帧放入即可。 当然需要注意的是,如果仅仅使用简单的分页思想,是无法解决虚拟空间未分配空间对物理内存的占用问题。所以一般会结合分段一起使用。这样既可以使虚拟地址空间未分配空间不会占用物理内存,同时解决物理内存的碎片问题(虽然到处是碎片,但我有映射,不怕这个碎片) ![分页][4] ### 分段、分页混合方法 ![分段-分页][5] 与上文中所述的混合方法中的虚拟地址对应如下: ![分段、分页混合方法的虚拟地址][6] ### 地址转换缓存TLB 分页技术中,虚拟地址与实际物理地址的映射称为页表(储存在内存中),如果不使用分段技术,显而易见,那么页表是巨大的,所以使用分段技术同时可以使得分页技术更加有效率。而且为了加速这个映射过程,在硬件上,有专门的技术来加速,称为快速地址转换缓存(TLB,translation-lookaside buffer),对于每次内存访问,硬件都会检查TLB,看看其中是否有期望的映射,如果有,就完成这个转换。不需要访问页表。 [1]: http://assets.processon.com/chart_image/60765ce21e08534f371d0d75.png [2]: http://assets.processon.com/chart_image/607443d5f346fb70967e113c.png [3]: http://assets.processon.com/chart_image/6074511c63768912ae560521.png [4]: http://assets.processon.com/chart_image/60764bbd1e08534f371c9d9b.png [5]: http://assets.processon.com/chart_image/607662d2e401fd2d6696adaa.png [6]: http://assets.processon.com/chart_image/60765a7ff346fb647a4dcd39.png 最后修改:2021 年 04 月 14 日 12 : 28 PM © 允许规范转载