前言
虚拟存储器(Virtual Memory, VM)应用于现代各种规模的计算机系统中,包括数据中心、台式机、平板电脑、手机、可穿戴设备,甚至是嵌入式系统,虚拟存储器为程序员提供了干净实用的编程模型。虚拟存储器是对给定机器上实际可用的存储资源的理想化抽象。程序只使用虚拟地址执行内存访问,处理器和操作系统一起将这些虚拟地址转换为存储这些数据的实际物理位置的物理地址,如下图所示。
为什么需要虚拟存储器
虚拟存储器允许程序可以任意使用处理器的地址资源,不需要考虑地址的限制和其它并发程序,每个程序都认为处理器中只有自己在运行。这反过来又有利于代码的移植,不管是因为处理器上利用率的动态变化,还是移植到另一台具有完全不同物理资源的机器上。在实际中,用户级进程通常甚至无法确定在后台使用的物理地址。如果没有虚拟地址,程序员必须了解物理内存空间的一些低层次资源,比如有几块RAM、硬盘、闪存等等,这样方便编写代码。每次RAM容量或配置的变化,程序员都需要重写和重新编译他们的代码。
虚拟存储器提供了内存保护和隔离功能,可以防止错误或恶意代码的攻击,以及进程访问不应该访问的内存空间。如果没有虚拟存储器,程序将能够覆盖并破坏其它程序的内存数据,严重损害了安全性。
虚拟存储器允许程序的大小可以超过实际物理内存的大小,操作系统把当前使用的部分内容放到物理内存中,而把其它其它未使用的内容交换(swap)到更下一级存储器,如硬盘(disk)或闪存(flash)上。因此,虚拟地址空间和物理地址空间的大小可以不同,每个程序都可以忽略物理实现细节或可能共享该系统的任何其它程序。
虚拟存储器还负责内存管理任务,比如内存的定期分配和回收,差劲的虚拟存储器容易导致内存碎片。在这种情况下,地址空间中的内存区域的低效设计会导致不可访问和资源浪费。对于程序申请内存,虚拟存储器必须能够分配足够可用的资源,也必须处理申请内存超过可用的物理内存资源,这通常使用交换(swap)来实现的。
虚拟存储器方便内存从一个物理地址迁移到另一个物理地址,或者从一种物理内存类型迁移到另一种(例如,DRAM到非易失性内存),从一个设备到另一个设备(例如,CPU到GPU),甚至只是在一个物理内存中重新摆放内存区域。
虚拟存储器的一些思考
在一个典型的程序中,内存访问通常占指令的三分之一左右,因此在使用虚拟存储器的体系结构中,虚拟存储器的性能对整个系统的性能至关重要。除非系统使用VIVT缓存(Virtually Indexed, Virtually Tagged cache),否则每次load和store都要经过虚拟存储器。以此,地址转换必须不能消耗过多硬件和软件资源,或消耗过多的能量的方式实现。在一些研究中表明,虚拟存储器的成本不应该超过运行的3~20%。
正由于虚拟存储器的性能很关键,随着现在程序变得越来越大,虚拟存储器的硬件实现和操作系统算法受到挑战,促使在超页表和TLB预取等特性上的开发,来帮助虚拟存储器性能满足更大的工作负载。并且TLB结构、大小、组织、分配和替换策略的问题变得越来越重要。
而且现在计算机系统在架构上变得越来越异构,通常会集成GPU、DSP等加速器设备。这些设备和传统CPU共享虚拟地址空间,这就促进了许多有趣的研究,包括内存和设备之间的迁移页表技术、可扩展TLB同步算法,以及允许设备和CPU共享虚拟地址空间的IOMMU。
虚拟存储器是一个复杂的接口,需要正确的硬件和软件配合。尽管几十年的积极研究,现实世界的虚拟存储器实现仍然经常遇到硬件和操作系统层的错误。
微信号|chip_yes,微信公众号|专芯致志er