Lecture 34: VM III: TLB
OS: Supervisor Mode, Exceptions
回顾
陷阱处理异常/中断 (Traps Handle Exceptions/Interrupts)
陷阱处理程序(Trap Handler)是一段代码,专门用于处理系统中的中断和异常。中断和异常可以是异步的(如外部中断)或同步的(如在程序执行期间发生的页面错误)。
陷阱处理程序的处理流程包括以下几个步骤:
- 完成出错指令之前的所有指令:
- 在处理异常或中断之前,处理器会首先完成出错指令之前的所有指令。这是为了确保在错误发生之前的程序状态是完整且一致的。
- 清空出错指令之后的所有指令:
- 出错指令之后的所有指令都会被清空,通常这些指令会被转换为空操作(noops)或“气泡”(bubbles)。这一过程还包括清空出错的那条指令,以防止它对程序的执行产生进一步的影响。
- 将执行转移到陷阱处理程序:
- 一旦流水线清空,系统会将控制权转移给陷阱处理程序。陷阱处理程序通常在监督模式下运行,它可以选择处理完异常后返回原程序,并重新执行失败的指令。如果陷阱处理程序成功返回,对程序来说,异常或中断就像从未发生过一样,程序可以继续执行。
五级流水线中的异常处理 (Exceptions in a 5-Stage Pipeline)
在具有五级流水线的处理器架构中(如RISC-V),异常的处理与流水线中的数据冒险非常相似。
- 陷阱和流水线冒险的处理相似性:
- 流水线中的陷阱处理方式类似于数据冒险的处理。当处理器在流水线的某个阶段检测到异常时,它会在确保前置指令执行完毕的同时,将后续指令清空,并将控制权交给陷阱处理程序。
- 在RISC-V架构中的异常处理:
- 在RISC-V架构中,异常的原因可以通过出错指令及其所在的流水线阶段来推断。例如:
- PC地址异常:发生在指令获取阶段(IF)。
- 非法操作码异常:发生在指令解码阶段(ID)。
- 数据地址异常:发生在数据访问阶段(MEM)。
- 在RISC-V架构中,异常的原因可以通过出错指令及其所在的流水线阶段来推断。例如:
通过对流水线中不同阶段异常的识别和处理,处理器能够及时响应并修复错误,从而保持程序的正确性和系统的稳定性。
陷阱处理程序 (The Trap Handler)
陷阱处理程序是操作系统中用于处理异常和中断的重要机制。当系统遇到异常或中断时,它会暂停当前程序的执行,并将控制权转移给陷阱处理程序。
陷阱处理程序的执行步骤:
- 保存当前程序的状态:
- 陷阱处理程序首先保存当前程序的所有寄存器状态,以确保在处理完异常后,程序可以从中断点继续执行而不丢失任何状态信息。
- 确定异常或中断的原因:
- 系统需要识别引发异常或中断的具体原因。这可能是由于非法指令、页面错误、外部中断等不同的原因。
- 处理异常/中断:
- 根据异常的类型,陷阱处理程序执行相应的处理操作。处理完成后,系统可能会采取以下两种行动之一:
继续执行程序的路径:
- 恢复程序状态:
- 如果异常处理完成且程序可以继续执行,陷阱处理程序会恢复之前保存的程序状态。
- 返回控制权给程序:
- 最后,系统将控制权返回给程序,程序可以从中断点继续执行。对程序而言,异常处理就像什么都没发生一样,程序可以继续正常运行。
终止程序的路径:
- 释放程序资源:
- 如果异常或中断处理后,系统判断程序无法继续安全运行,陷阱处理程序将会终止该程序。首先,它会释放程序占用的所有资源,例如内存、打开的文件句柄等。
- 调度新程序:
- 在终止当前程序后,操作系统会调度其他的程序继续运行,以确保系统资源能够被有效利用。
处理上下文切换 (Handling Context Switches)
上下文切换是多任务操作系统的核心机制之一。它允许操作系统在不同的进程之间切换,使得一个单一的处理器能够看起来像是在同时运行多个程序。
上下文切换的基本步骤:
- 设置定时器:
- 操作系统设置一个定时器,用于控制上下文切换的时间。当定时器到期时,会触发一个硬件中断,提醒操作系统进行上下文切换。
- 保存当前进程的状态:
- 陷阱处理程序保存当前进程的所有寄存器状态,包括程序计数器(PC)和页表寄存器(SPTBR),以便稍后恢复该进程时能够继续执行。
- 加载下一个进程的状态:
- 系统加载下一个进程的寄存器状态,并将控制权转移到该进程,使其继续执行。
通过上下文切换,操作系统能够在多个进程之间分配CPU时间,确保系统的多任务处理能力。这使得多个进程能够共享系统资源,而不会相互干扰。
处理页面错误 (Handling Page Faults)
页面错误(Page Fault)发生在程序试图访问的内存页面不在物理内存(DRAM)中时。这通常意味着该页面目前驻留在磁盘上,而不是在快速访问的内存中。
- 页面错误的识别:
- 当程序访问某个地址时,系统会检查该地址对应的页表条目。如果页表条目的有效位(valid bit)被关闭,表示该页面不在DRAM中,从而触发页面错误。
- 页面错误的处理过程:
- 陷阱处理程序:一旦页面错误发生,陷阱处理程序会接管,启动将页面从磁盘加载到DRAM的过程。
- 页面交换:如果物理内存已满,操作系统可能需要将某些页面交换到磁盘,以腾出空间给新的页面。在这种情况下,系统会进行上下文切换,使CPU在页面加载期间可以继续处理其他任务。
- 重新执行指令:页面加载完成后,系统会更新页表,并重新执行引发页面错误的指令,以确保程序正常继续。
- 额外说明:
- 写保护违规(Write Protection Violations)也会触发异常,类似于页面错误的处理机制。
系统调用和应用程序启动 (System Calls and Launching Applications)
系统调用(Syscall)是一种特殊的“软件中断”,允许用户程序请求操作系统提供服务。系统调用类似于函数调用,但由操作系统内核来执行。
- 系统调用的作用:
- 系统调用允许用户程序执行各种操作系统服务,如创建和删除文件、读写文件、访问外部设备(如扫描仪)等。
- 例如,
printf
、malloc
等函数调用在RISC-V中通过ecalls
实现,都是通过系统调用与操作系统交互的。
- 应用程序启动的过程:
- 当一个Shell(用户进程)想要启动一个新应用时,它会通过系统调用(如Linux中的
fork
)进入操作系统内核。 - 在监督模式下,操作系统加载新程序,将控制权转移到新程序的
main
函数的起始地址,然后返回用户模式继续执行。 - Shell进程通常会等待新进程的
main
函数返回(使用join
),以便继续进行后续操作。
- 当一个Shell(用户进程)想要启动一个新应用时,它会通过系统调用(如Linux中的
这些过程展示了如何通过系统调用与操作系统交互,以及操作系统如何管理和启动新的应用程序,从而保持系统的正常运转。
OS: Boot
回顾
计算机启动时发生了什么?(1/2)
在计算机启动时,CPU执行的第一个指令集是从只读存储器(ROM)中获取的。这与Venus模拟器的行为相似。
- CPU启动执行:
- 当计算机开机时,CPU从ROM中存储的某个预定地址开始执行指令。在图中,PC(程序计数器)初始指向0x2000(这是一个默认值)。ROM中通常存储了基本的固件代码,它用于初始化硬件设备并准备系统的启动过程。
- 这段代码通常是固化在硬件中的,不需要从磁盘加载,因此即使在磁盘还没有初始化之前,CPU也可以开始执行这些指令。
计算机启动时发生了什么?(2/2)
当CPU执行完ROM中的指令后,它会启动BIOS(基本输入输出系统),接着引导程序(bootloader)会加载操作系统内核,完成启动过程。
- BIOS:
- BIOS负责执行一系列基本硬件检查,确保系统的各个部分正常工作。然后,它会找到一个存储设备(例如硬盘或SSD),并加载第一个扇区的数据。这个数据通常是引导加载程序(bootloader)的起始部分。
- 引导加载程序(Bootloader):
- 引导加载程序通常存储在磁盘上。它的任务是将操作系统内核从磁盘加载到内存中,并将控制权移交给操作系统。这一步骤至关重要,因为它是系统从硬件启动过渡到操作系统控制的桥梁。
- 操作系统启动(OS Boot):
- 一旦内核被加载,操作系统会开始初始化各种服务和驱动程序。这些服务和驱动程序使得操作系统可以与硬件进行通信,并为用户提供一个稳定的操作环境。
- Init进程:
- 在初始化完成后,操作系统会启动一个初始进程(通常称为Init进程)。这个进程可能会启动一个终端、桌面环境或其他等待用户输入的程序,从而完成整个系统的启动过程。此时,计算机已经完全启动,准备好接受用户的操作。
这两部分内容展示了从硬件电源开启到操作系统完全加载之间的关键步骤,是理解计算机启动过程的重要基础。
Caches vs. Virtual Memory
缓存与虚拟内存
现代内存层次结构
现代计算机系统的内存层次结构是一个分层设计,从最快的存储设备(如CPU寄存器)到最慢的存储设备(如磁盘存储)。这个层次结构的设计目的是在性能和成本之间找到最佳平衡,同时最大化存储容量。
各层次存储设备的特点
- 寄存器:
- 速度:极快,通常在纳秒级别。
- 容量:非常小,通常在KB范围内。
- 位置:位于CPU内部,直接与处理器核心相连,用于存储正在处理的数据。
- CPU缓存(L1、L2、L3):
- 速度:比寄存器稍慢,但仍然非常快。L1缓存速度最快,L2和L3依次减慢。
- 容量:L1缓存通常为几十KB,L2缓存为几百KB到几MB,L3缓存可以达到几十MB。
- 功能:缓存用于暂存频繁访问的数据,减少CPU访问主存储器的时间。它们通过将数据分块(通常为64字节)存储来加速数据访问。
- 主存储器(DRAM):
- 速度:相对缓存慢得多,通常在数百纳秒到微秒之间。
- 容量:显著大于缓存,通常在GB范围内。
- 作用:主存储器用于存放正在运行的程序和当前处理的数据。它与CPU通过内存总线连接,处理器从中读取数据时会比从缓存读取慢。
- 虚拟内存和二级存储器(如SSD和HDD):
- 速度:最慢的存储设备,通常在毫秒级别,特别是传统的机械硬盘(HDD)。
- 容量:最大,可以达到数TB甚至更多。
- 用途:用于存储不常用的数据和程序。当物理内存不足时,虚拟内存系统会将不活跃的数据移到二级存储器中。
内存管理的单元
内存系统使用不同的单位来管理数据,主要包括缓存块和内存页。
- 缓存块(Cache Blocks):
- 缓存是以块为单位进行管理的。一个块通常包含64字节的数据。L1、L2、L3缓存使用这些块来加速数据访问,通过在较低级别的存储器(如主存)中预取数据块,并存储在缓存中,减少CPU访问时间。
- 内存页(Memory Pages):
- 主存储器和虚拟内存通常以页为单位进行管理。一个页通常为4KiB。这些页面有助于操作系统进行内存管理和虚拟地址到物理地址的转换。虚拟内存通过将不常用的页面移到磁盘上来扩展物理内存的容量。
缓存与主存储器的区别
缓存和主存储器的主要区别在于其管理和操作方式:
- 数据粒度:
- 缓存以小块(通常为64字节)的粒度进行操作,以确保快速数据访问。缓存的设计重点在于加速数据访问,减少CPU等待时间。
- 主存储器则以更大的页面(通常为4KiB)的粒度进行管理,允许更高效的内存分配和管理。
- 访问时间:
- 缓存的访问时间远低于主存储器。L1缓存几乎可以在一个时钟周期内完成数据访问,而访问主存储器则需要几十到几百个时钟周期。
- 数据一致性:
- 在多处理器系统中,缓存一致性协议(如MOESI协议)确保各处理器缓存中的数据保持一致。这对于保持数据的正确性和系统的稳定性至关重要。
- 物理与虚拟内存的结合:
- 虚拟内存利用磁盘存储作为扩展的内存空间,通过页表将虚拟地址映射到物理地址,使得程序可以使用比实际物理内存更大的地址空间。这个过程是透明的,程序不会意识到它的数据实际上存储在磁盘而非物理内存中。
理解内存层次结构及其操作方式对于优化程序性能和提高系统效率至关重要。随着数据在内存层次结构中逐层移动,访问速度降低,但容量增大。通过有效地利用缓存、主存储器和虚拟内存,计算机系统能够在性能和成本之间取得平衡,并处理大规模数据的存储和访问需求。
缓存 vs. 页表
在计算机系统中,缓存和页表都是关键的内存管理机制,它们在提高系统性能和管理内存资源方面发挥了不同的作用。我们将对这些概念进行深入分析和扩展,以帮助理解它们在内存层次结构中的角色和差异。
缓存的作用
缓存是内存层次结构中的重要组成部分,旨在加速数据访问。系统中的每一级缓存都存储着更低一级内存的部分数据副本,以便更快地访问这些数据。
- L1和L2缓存:
- 这两个缓存层次分别存储从主存(DRAM)中提取的块。这些块是数据的副本,通常大小为32B到64B。缓存的存在使得处理器在执行指令时不必频繁访问较慢的DRAM,从而显著提高了系统的响应速度。
- 缓存失效处理:当缓存未命中(Cache Miss)时,系统必须从更低层级的存储器中加载数据。这种加载过程需要时间,因此缓存的设计重点在于最大限度地减少缓存未命中的频率。
- DRAM与磁盘之间的关系:
- 类似地,DRAM中的数据页实际上是磁盘上数据页的缓存副本。数据首先被加载到DRAM中,然后由操作系统在需要时访问。这样,系统可以通过减少对磁盘的访问来提升性能,因为磁盘的访问速度远慢于DRAM。
缓存通过将数据从较慢的存储器逐层复制到较快的存储器中,使计算机系统在性能和存储容量之间取得了平衡,从而提高了整体运行效率。
页表的功能
页表在内存管理中扮演着关键角色,主要负责地址转换,即将虚拟地址转换为物理地址。页表存储物理页号(Physical Page Numbers, PPN),使操作系统能够正确地定位和管理内存中的数据。
- 地址转换:
- 当CPU生成一个虚拟地址时,页表会将虚拟页号(VPN)映射到物理页号(PPN),然后结合偏移量生成实际的物理地址。这一过程确保了每个进程可以在自己的虚拟地址空间中运行,而不需要直接访问物理内存。
- 请求分页(Demand Paging):
- 页表还支持请求分页机制。当一个进程试图访问某个数据页而该页不在内存中时,会触发页面错误(Page Fault)。操作系统通过页表获取数据页在磁盘上的位置,并将其加载到内存中。
- 页表通过跟踪每个页面的状态(如是否在内存中、是否被修改等)来确保操作系统能够有效地管理内存资源,并在需要时快速响应页面请求。
缓存与请求分页的对比
尽管缓存和请求分页都是为了提高数据访问效率,但它们在具体实现和应用场景上存在显著差异:
- 内存单元:
- 缓存:以块为单位,通常为32B到64B。
- 请求分页:以页为单位,通常为4KiB到8KiB。
- 失效处理:
- 缓存:缓存未命中时,系统从主存中加载数据块。
- 请求分页:页缺失时,系统从磁盘中加载整个页面到内存。
- 数据关联性:
- 缓存:缓存可以采用直接映射、N路集合关联或全关联的方式进行管理。
- 请求分页:通常是全关联的,意味着磁盘中的任何页面都可以被加载到DRAM中的任何位置。
- 替换策略:
- 缓存:常用的替换策略包括最近最少使用(LRU)或随机替换(Random)。
- 请求分页:替换策略常用LRU、先进先出(FIFO)或随机替换。
- 写策略:
- 缓存:缓存的写策略包括写直达(Write-through)和回写(Write-back)。
- 请求分页:通常采用回写(Write-back)方式,即只有当页面被替换时,才将修改后的数据写回磁盘。
缓存和页表分别在内存层次结构的不同层面上工作。缓存主要用于加速CPU对数据的访问,减少对较慢存储层(如DRAM或磁盘)的依赖。页表则用于管理虚拟内存,提供进程间的内存隔离和保护,同时支持请求分页以有效利用物理内存。理解这两者的作用及其区别对于优化系统性能至关重要。
The Translation Lookaside Buffer
现代虚拟内存系统的概述
现代虚拟内存系统是通过地址转换机制来提供大容量、私有且统一的存储体验。这种系统设计带来了两个主要的优势:
- 隐私性(Privacy):
- 隐私性也意味着保护(Protection)。在现代计算机系统中,每个用户或进程都有自己独立的虚拟地址空间。这种独立性确保了不同用户或进程的数据不会互相干扰,即使它们运行在同一台机器上。这样可以防止恶意程序或错误操作影响其他进程的数据,从而提高系统的安全性和稳定性。
- 统一存储(Uniform Storage):
- 统一存储主要体现在请求分页(Demand Paging)机制的应用上。虚拟内存允许程序运行在比物理内存(DRAM)更大的虚拟地址空间中。这种设计使得程序可以处理比实际物理内存更大的数据集,同时在不同配置的计算机之间提供一致的操作环境。用户或开发者无需关注底层硬件的差异,虚拟内存系统会自动管理内存的分配和回收。
虚拟内存的代价
尽管虚拟内存系统带来了显著的好处,但其代价也不可忽视。每次内存访问都需要进行地址转换,而页表存储在内存中,这意味着每次访问都会导致额外的内存操作,进而增加平均内存访问时间。
- 地址转换的性能瓶颈:
- 如果直接从内存中的页表进行地址转换,那么每次指令或数据访问可能都需要多次内存访问,这会显著拖慢系统的速度。
- 对于单级页表,每次内存访问需要2次内存操作:一次用于读取页表项,一次用于实际的数据访问。
- 对于多级页表,情况更加复杂。比如在两级页表结构中,每次内存访问可能需要进行3次内存操作:两次用于页表遍历(Page Table Walk),一次用于实际的数据访问。
加速地址转换的解决方案
为了克服地址转换带来的性能瓶颈,必须加速这个过程,使其在每个时钟周期内完成且占用最少的资源。解决这一问题的关键技术是翻译后备缓冲(Translation Lookaside Buffer, TLB)。
TLB 是用于地址转换的缓存
Translation Lookaside Buffer(TLB) 是一种用于加速地址转换的高速缓存。TLB 的主要功能是存储页表中的部分条目,以便在虚拟地址需要转换为物理地址时,能够快速完成转换过程。
TLB 的工作机制
当处理器需要访问一个虚拟地址(Virtual Address, VA)时,它首先会检查 TLB 中是否有该虚拟地址对应的物理地址(Physical Address, PA)。具体过程如下:
- TLB 命中(TLB hit):
- 如果 TLB 中已经存储了该虚拟地址对应的条目,那么处理器可以在一个时钟周期内完成地址转换,而无需访问内存中的页表。这种情况极大地加速了内存访问,提高了系统性能。
- TLB 未命中(TLB miss):
- 如果 TLB 中没有找到该虚拟地址对应的条目,那么系统必须进行页表遍历(Page Table Walk)。在页表遍历中,处理器需要访问内存,找到该虚拟地址对应的物理地址,并将此条目添加到 TLB 中,以便未来的访问可以更快地完成。
TLB 的设计与性能
TLB 的设计对系统性能至关重要,以下是 TLB 设计的关键要素:
- TLB 条目的数量与覆盖范围:
- TLB 的条目数量通常在 38 到 128 个之间。每个条目存储一个虚拟页号(VPN)和对应的物理页号(PPN),覆盖一定范围的虚拟地址空间。TLB 的覆盖范围(TLB Reach)决定了 TLB 可以同时映射的虚拟地址空间的最大大小。
- 完全相联设计(Fully Associative):
- 为了最大化 TLB 的命中率,TLB 通常采用完全相联的设计。这意味着任何虚拟页号都可以映射到 TLB 中的任何条目,减少了因条目冲突导致的未命中。这种设计提高了 TLB 的灵活性和命中率。
- 替换策略:
- 当 TLB 满了之后,需要替换掉一个条目以存入新的条目。常见的替换策略包括随机替换(Random Replacement)和先进先出(FIFO)。这些策略决定了在 TLB 已满时,应该替换掉哪个条目,以确保新的条目能够被添加进去。
通过使用 TLB,处理器可以大幅减少对内存中页表的访问次数。这不仅降低了内存访问的延迟,还提升了整个系统的效率,尤其是在需要频繁进行地址转换的应用场景中,TLB 的作用尤为关键。
标签、索引和偏移(Tag, Index, and Offset)
在现代计算机系统中,虚拟内存的地址转换和数据缓存的访问都依赖于标签、索引和偏移机制。这些机制在 TLB(Translation Lookaside Buffer) 和数据缓存中的应用有些相似,但也有关键的区别。
TLB 中的标签、索引和偏移
TLB 是用于加速虚拟地址到物理地址转换的高速缓存。虚拟地址可以分为三个部分:TLB标签(TLB Tag)、TLB索引(TLB Index)和偏移量(Offset)。
- TLB标签(TLB Tag):
- TLB标签用于标识特定的TLB条目,类似于缓存中的标签。每个条目包含一个标签,用于确认当前TLB条目是否对应请求的虚拟页。
- 当处理器提供一个虚拟地址时,系统首先根据TLB索引定位到TLB中的一个特定条目。然后,系统会检查TLB标签,看该条目是否与请求的虚拟页号匹配。
- 如果匹配成功,TLB将直接提供对应的物理页号(PPN),从而加速地址转换。
- TLB索引(TLB Index):
- TLB索引用于定位TLB中的特定条目。这个索引通常是通过虚拟地址中的某些位来决定的。
- 通过索引,系统可以快速找到存储在TLB中的可能条目,大大缩短了查找时间。
- 偏移量(Offset):
- 偏移量用于确定物理地址中的具体位置。在确定了物理页号(PPN)之后,偏移量用于计算出最终的物理地址。
- 偏移量直接从虚拟地址中获取,并且在地址转换过程中不会发生变化。
数据缓存中的标签、索引和偏移
在数据缓存中,物理地址也被分为三个部分:标签(Tag)、索引(Index)和块偏移量(Block Offset)。
- 标签(Tag):
- 数据缓存中的标签用于识别缓存中的每个块是否对应请求的物理地址。
- 当一个物理地址被提供时,系统通过索引找到对应的缓存行,然后检查标签是否与缓存行中的标签匹配。如果匹配,则命中(hit),并可以直接从缓存中读取数据。
- 索引(Index):
- 索引用于定位缓存中的特定行。缓存中的行数是有限的,因此索引决定了物理地址在缓存中的具体位置。
- 索引通过物理地址中的某些位来确定,类似于在TLB中使用索引定位条目的方式。
- 块偏移量(Block Offset):
- 块偏移量用于确定缓存行中的具体字节或字。每个缓存行通常包含多个字节,因此需要使用块偏移量来精确定位需要的数据。
- 这个偏移量直接决定了访问缓存行中的哪一部分数据。
理解标签、索引和偏移的重要性
在现代计算机系统中,虚拟地址与物理地址之间的转换,以及数据在缓存中的存储和访问,都涉及到标签、索引和偏移的概念。理解这些机制有助于我们优化内存管理和提高数据访问效率。
- 虚拟地址与物理地址的独立性:
- 虚拟地址和物理地址在TLB和数据缓存中分别有各自的标签、索引和偏移。这意味着同一个虚拟地址和物理地址在不同的内存层次中,它们的标签和索引可能不相同。
- TLB主要用于加速虚拟地址到物理地址的转换,而数据缓存则用于实际的数据存储和快速访问。这两个层次之间的独立性使得系统可以更灵活地管理内存和提高数据访问的效率。
通过深入理解这些机制,开发者和系统架构师可以更好地设计和优化计算机系统,确保内存管理的高效性和数据访问的快速性。
内存访问:TLB、缓存、DRAM、页表?
在讨论内存访问时,我们需要理解几个关键组件是如何协同工作的:TLB(翻译后备缓冲区)、缓存(Cache)、主存(DRAM)和页表(Page Table)。
-
缓存能否保存请求的数据,如果对应的页面不在主存中?
答案是否定的。如果对应的页面不在主存(DRAM)中,那么缓存也不可能保存请求的数据。缓存是主存的一个快速存储副本,它只能加速对已存在于主存中的数据的访问。因此,如果某个页面未加载到主存中,首先需要通过页表找到并加载该页面,然后才能将其缓存。
-
在一次内存引用中,我们应该首先访问哪个块?什么时候应该翻译虚拟地址?
对于这个问题,我们通常假设使用物理索引、物理标签的缓存设计(Physically Indexed, Physically Tagged Caches)。这意味着在进行缓存访问之前,首先要完成虚拟地址到物理地址的转换。
具体流程如下:
- 首先,CPU生成一个虚拟地址(VA),并将其发送给TLB。
- 如果TLB命中,TLB会直接提供对应的物理地址(PA)。
- 使用该物理地址查找缓存。如果缓存命中,直接返回缓存中的数据。
- 如果TLB未命中,则需要访问页表来获取物理地址。
- 一旦得到了物理地址,如果缓存未命中,则需要访问主存(DRAM),从而获取数据。
这里的关键点是TLB首先完成地址转换,然后缓存根据物理地址进行数据访问。这种顺序能够最大化内存访问的效率,并且确保缓存始终访问有效的物理地址数据。
通过以上步骤,我们可以更好地理解在现代计算机系统中内存访问的复杂性,特别是在使用虚拟内存的情况下,各个子系统如何协调工作来保证数据的高效读取。
TLBs in the Datapath
虚拟内存与CPU流水线
虚拟内存在现代计算机体系结构中扮演着至关重要的角色,尤其是在CPU流水线操作过程中。虚拟内存不仅提供了地址翻译的机制,还在系统的安全性和内存管理中起到关键作用。以下是虚拟内存在CPU流水线中作用的深入解析:
地址翻译与功能检查的核心步骤
- 每个指令/数据访问 = 地址翻译 + 功能检查
- 指令TLB(Instruction TLB)和数据TLB(Data TLB):这两个缓存器分别负责将虚拟地址转换为物理地址。指令TLB在指令获取阶段工作,而数据TLB在数据访问阶段工作。它们通过快速查找已缓存的地址转换信息,加速CPU的操作。
- 指令解码与执行:在指令被解码后,CPU将根据指令类型执行相应的操作。这些操作可能涉及内存访问,因而需要依赖TLB完成快速的地址转换。
- 处理步骤的深入解析
- TLB未命中:当虚拟地址在TLB中未找到时,系统会启动硬件机制进行页表遍历(Page Table Walk),以找到相应的物理页号(PPN)。这个过程虽然较慢,但对于确保地址翻译的准确性至关重要。
- 页错误处理(Page Fault Handling):如果所需页面不在物理内存中(即发生页错误),系统将触发一个精确的陷阱(trap),暂停当前指令的执行,等待操作系统将页面从磁盘加载到内存中,然后重新开始执行该指令。
- 保护检查:每次内存访问都会经过严格的权限检查,以确保操作合法。如果操作试图访问受保护的内存区域,如写入一个只读页面,则会触发保护错误(Protection Fault),通常导致进程被终止。
虚拟内存操作流程图
为了更好地理解虚拟内存操作的复杂性,以下是从虚拟地址转换到物理地址的详细操作流程:
-
TLB查找:首先,CPU会在TLB中查找与虚拟地址相关的条目,以确定是否可以直接获得物理地址。如果查找成功,则直接完成地址转换。
-
页表遍历(Page Table Walk):如果TLB查找失败(TLB未命中),CPU将启动页表遍历过程。页表遍历通过查找多级页表,找到与虚拟页号(VPN)对应的物理页号(PPN)。
-
保护检查:地址转换后,系统会检查访问权限。这一检查确保当前操作符合内存访问的安全规则,如只读或读写权限。如果违反了权限规定,将会触发保护错误。
-
地址转换结果与后续操作
- 页面在内存中:如果页面已加载到内存中,系统会更新TLB以加速未来的访问,并将转换后的物理地址发送到数据缓存,完成当前指令的执行。
- 页面不在内存中:如果页面未加载到内存中,会触发页面错误。操作系统将从磁盘中加载页面,并可能执行上下文切换以处理其他任务,直到页面加载完成。
- 保护错误处理:如果访问操作违反了内存保护规则,如非法写入,将导致保护错误。这通常表现为操作系统终止相关进程,并返回错误信息(例如SEGV信号,在UNIX系统中表示段错误)。
虚拟内存与CPU流水线的整体影响
这整个流程展示了虚拟内存在确保CPU流水线平稳运行中的关键作用。它不仅提供了必要的地址翻译,还确保了系统的安全性和稳定性。通过结合硬件(如TLB)和软件(如操作系统的页面管理)层面的操作,虚拟内存机制在现代计算机系统中实现了高效的内存管理和数据保护。
处理上下文切换和TLB管理
在多任务操作系统中,上下文切换(context switch)是指操作系统暂停当前运行的进程,并将其上下文保存起来,以便稍后恢复。然后,操作系统加载并运行另一个进程的上下文。由于上下文切换涉及进程状态的保存和恢复,因此应尽可能快,以减少对系统性能的影响。
上下文切换的优化
- 页表的保留:
- 操作系统将所有当前运行进程的页表保留在DRAM中,而不是在每次上下文切换时频繁更新。这种策略确保每个进程的页表在其切换回来时立即可用,从而避免了在磁盘或内存中频繁查找和加载页表的高昂开销。
- TLB的管理:
- 在上下文切换时,操作系统必须确保TLB中的条目与当前活跃进程的页表一致。通常的做法是将所有TLB条目标记为无效,以防止旧进程的条目在新进程中被误用。也有其他策略,如部分无效化或标记切换,取决于硬件的支持。
上下文切换的步骤
- 定时器中断:
- 操作系统通过设置一个定时器来控制上下文切换。当定时器到期时,硬件触发中断,暂停当前进程的执行。
- 中断处理程序(Trap handler):
- 中断处理程序负责保存当前进程的上下文,包括所有的寄存器状态(如程序计数器PC和页表基址寄存器SPTBR)。
- 保存完成后,中断处理程序会清空或无效化TLB中的条目,以确保下一个进程使用的是正确的内存映射。
- 加载新进程:
- 中断处理程序加载下一个进程的上下文,包括其寄存器状态和页表设置。
- TLB重新加载,确保新进程的地址转换能够正确进行。
- 恢复用户模式:
- 最后,操作系统返回用户模式,继续执行新进程。这一过程确保了进程之间的隔离和数据安全,同时使得CPU资源得到最大化利用。
一个完整的基于页的虚拟内存系统
在虚拟内存系统中,页表和TLB共同作用,实现了地址转换、内存保护和进程隔离。以下是一个基于页的虚拟内存系统的工作流程:
虚拟地址转换
- TLB查找:
- 当CPU需要访问某个内存地址时,它首先在TLB中查找该虚拟地址的物理地址映射。如果TLB命中,则可以直接使用缓存的物理地址。
- 页表遍历:
- 如果TLB未命中,CPU会触发页表遍历。这是通过硬件页表遍历器(Hardware Page Table Walker)完成的。它在内存中的页表中查找虚拟页号(VPN)对应的物理页号(PPN),并将其加载到TLB中以加速后续访问。
- 页面错误处理:
- 如果页表遍历未找到该页(例如,该页未加载到内存),会发生页面错误(Page Fault)。此时,操作系统会暂停当前进程,将所需的页面从磁盘加载到内存,并更新页表。加载完成后,进程可以继续执行。
内存保护和安全检查
- 访问权限检查:
- 在地址转换过程中,系统还会检查当前进程是否具有访问请求页面的权限。这包括检查是否有读写权限、是否访问了受保护的内存区域等。
- 保护错误处理:
- 如果进程试图访问未授权的内存区域(如写入只读页面),操作系统会触发保护错误。这通常会导致进程被终止,防止潜在的安全漏洞或数据损坏。
通过这些机制,虚拟内存系统不仅实现了高效的内存管理,还确保了进程之间的隔离和系统的安全性。TLB的使用显著提高了地址转换的效率,使得即使在复杂的内存访问场景中,系统依然能够保持较高的性能。
VM Performance
现代内存层次结构
现代计算机的内存层次结构由多个存储层次组成,每一层次的存储设备都有不同的访问速度和容量,以满足性能和成本之间的平衡需求。这一结构包括寄存器、缓存、主存(DRAM)、以及二级存储(如磁盘)。
缓存策略与虚拟内存策略
- 缓存策略:缓存策略主要负责在处理器的缓存和主存(DRAM)之间管理数据的交换。它决定了哪些数据应保留在较快的缓存中以提高访问速度,而哪些数据应存储在较慢但容量更大的主存中。
- 虚拟内存的作用:虚拟内存系统扩展了物理内存的容量,使得主存能够充当类似于缓存的角色,而磁盘则成为了最低层次的存储设备。虚拟内存策略负责在主存和磁盘之间管理数据的传输,确保在需要时数据可以快速从磁盘加载到主存中。
- TLB(Translation Lookaside Buffer):TLB在缓存之前发挥作用,但它直接影响了虚拟内存系统的性能,因为它决定了虚拟地址如何快速转换为物理地址。如果TLB命中率较高,系统可以减少访问页表的开销,从而加快内存访问速度。
平均内存访问时间(AMAT)
AMAT公式
平均内存访问时间(AMAT)是衡量内存层次结构性能的一个关键指标。AMAT公式如下:
\[ AMAT = \text{命中时间} + (\text{未命中率} \times \text{未命中惩罚}) \]
- 命中时间:指的是当所需数据在当前层次的缓存中时所需的访问时间。
- 未命中率:指的是数据未能命中的概率。
- 未命中惩罚:指的是当未命中时,系统需要花费额外的时间从下一层次存储设备(如主存或磁盘)中获取数据。
主存角色的变化
在引入虚拟内存后,主存(DRAM)成为了类似于中层缓存的角色,而磁盘则成为了最低层次的存储设备。这种角色的变化意味着主存也有一个命中率,系统需要确保主存的命中率足够高以减少访问磁盘的次数,从而优化整体性能。
设计问题
在设计内存层次结构时,关键问题之一是确定一个合理的命中率。理想的命中率取决于具体的应用场景和系统的设计目标。例如,对于实时系统,较低的未命中率至关重要,而对于数据密集型应用,可能需要更大容量的缓存或更复杂的缓存策略。
AMAT 与需求分页
在需求分页情况下,平均内存访问时间(AMAT)的计算变得更加复杂。需求分页增加了内存层次结构中的额外延迟,因为它涉及从磁盘加载页面的过程。
缓存层次的AMAT计算
假设以下层次结构:
- L1 缓存:
- 命中时间:1个时钟周期
- 命中率:95%
- L2 缓存:
- 命中时间:10个时钟周期
- 命中率:60%(针对L1未命中的情况)
- DRAM(主存):
- 命中时间:200个时钟周期
- 命中率:假设需要计算
- 磁盘:
- 命中时间:20,000,000个时钟周期(约10毫秒,假设处理器频率为2GHz)
没有需求分页的AMAT计算
在没有需求分页的情况下,AMAT的计算如下:
\[ AMAT_{no} = 1 + 5\% \times (10 + 40\% \times 200) = 5.5 \text{ 时钟周期} \]
这个结果表示,如果系统没有涉及需求分页,平均内存访问时间为5.5个时钟周期。
有需求分页的AMAT计算
在引入需求分页后,AMAT的计算变得复杂,尤其当未命中导致访问磁盘时:
\[ AMAT_{dp} = 5.5 + (5\% \times 40\% \times (200 + (1 - HR_{mem}) \times 20,000,000)) \]
其中,\[ HR_{mem} \] 是主存(DRAM)的命中率。
这个公式展示了需求分页对性能的影响,尤其是当访问磁盘的惩罚时间非常高时。如果主存的命中率不够高,访问磁盘的频率将显著增加整体的AMAT。
无需求分页的AMAT计算
在没有需求分页的情况下,AMAT的计算相对简单:
\[ AMAT_{no} = \text{L1命中时间} + \text{L1未命中率} \times (\text{L2命中时间} + \text{L2未命中率} \times \text{DRAM命中时间}) \]
带入具体数据:
\[ AMAT_{no} = 1 + 5\% \times (10 + 40\% \times 200) = 1 + 0.05 \times (10 + 0.4 \times 200) \]
\[= 1 + 0.05 \times (10 + 80) = 1 + 4.5 = 5.5 \text{时钟周期} \]
这个结果表示,在没有涉及需求分页的情况下,平均内存访问时间为5.5个时钟周期。
有需求分页的AMAT计算
在引入需求分页后,情况变得复杂。当L1和L2缓存都未命中时,系统需要访问主存(DRAM)。如果主存也未命中(页面不在DRAM中),系统将不得不从磁盘加载页面。
这时,AMAT公式需要考虑以下几点:
- 主存的未命中率:如果主存未命中,则意味着需要从磁盘加载页面。
- 磁盘访问的惩罚时间:磁盘访问的惩罚时间非常高(20,000,000个时钟周期)。
因此,AMAT公式可以表示为:
\[ AMAT_{dp} = \text{无需求分页的AMAT} + \text{从主存未命中导致的额外时间} \]
其中,额外时间可以表示为:
\[ \text{从主存未命中的惩罚} = \text{L1未命中率} \times \text{L2未命中率} \times \left(\text{DRAM访问时间} + \left(1 - HR_{mem}\right) \times \text{磁盘访问时间}\right) \]
所以,完整的AMAT公式为:
\[ AMAT_{dp} = 5.5 + \left(5\% \times 40\% \times \left(200 + \left(1 - HR_{mem}\right) \times 20,000,000\right)\right) \]
公式解释
- 基础AMAT:无需求分页的AMAT(5.5个时钟周期)作为计算的起点。
- 主存未命中导致的额外时间:
- 5% 是L1缓存的未命中率。
- 40% 是L2缓存的未命中率(针对L1未命中的情况)。
- 200 是主存的命中时间。
- (1 - HR_{mem}) 表示主存未命中率,即页面不在主存中的概率。
- 20,000,000 是磁盘访问时间(时钟周期)。
通过该公式可以看出,如果主存的命中率(HR_{mem})不够高,未命中会导致访问磁盘的频率增加,极大地增加整体的AMAT。因此,高效的需求分页和高命中率是确保系统性能的关键。
结论
为了尽量减少需求分页对系统性能的影响,主存的命中率必须接近100%,甚至达到99.9999%。这种高命中率可以确保即使在涉及需求分页的情况下,AMAT仅会轻微增加,维持在一个可以接受的范围内(例如5.9个时钟周期),从而确保系统性能的稳定性和效率。
对不同命中率的分析
内存命中率(HR)对系统性能的影响非常大,尤其是在需求分页的情况下。下面我们详细分析了不同命中率对平均内存访问时间(AMAT)的影响:
- HR_{mem} = 99%:
- AMAT = 4,005.5个时钟周期。
- 分析:这种情况下,虽然99%的命中率看起来很高,但在每20,000次内存访问中有一次会触发对磁盘的访问,由于磁盘访问的巨大开销,整体AMAT显著增加。这意味着即使内存有很高的命中率,但一旦发生未命中,导致系统性能严重下降。
- HR_{mem} = 99.9%:
- AMAT = 405.5个时钟周期。
- 分析:在这种命中率下,虽然系统性能有所改善,但仍不足以满足高性能应用的需求。虽然页面错误率已经显著降低,但因为磁盘访问的代价仍然很高,系统性能依旧较低。
- HR_{mem} = 99.9999%:
- AMAT = 5.9个时钟周期。
- 分析:这是一个理想的情况,显示出非常低的页面错误率(<0.01%)对于保持高性能至关重要。在这种情况下,绝大多数内存访问都是在主存中完成的,磁盘访问几乎被完全避免,使得AMAT接近于没有分页的理想水平。
总结
确保主存的高命中率对于维持系统性能至关重要。特别是在需求分页的情况下,哪怕只有极少的未命中都会显著拖累系统性能。高达99.9999%的命中率是理想的,能够将AMAT保持在接近无分页的状态,从而最大限度地提高系统效率。
TLB(翻译后备缓冲器)条目中的位数计算
在虚拟内存系统中,翻译后备缓冲器(TLB) 是用于加速虚拟地址到物理地址转换的关键组件。下面是具体系统配置下,计算每个TLB条目所需的位数的详细过程:
系统配置参数
- 页面大小:16 KiB
- 虚拟地址大小:40位
- 物理内存大小:64 GiB
- TLB配置:2路组相联TLB,共512个条目
位数计算
- 虚拟页号(VPN):
- 虚拟地址大小为40位,页面大小为16 KiB(\(2^{14}\)字节)。
- 虚拟页号的位数 = 40 - 14 = 26位。
- 物理页号(PPN):
- 物理内存大小为64 GiB(\(2^{36}\)字节),页面大小为16 KiB。
- 物理页号的位数 = 36 - 14 = 22位。
- TLB条目结构:
- 有效位(Valid bit):1位,用于指示TLB条目是否有效。
- 脏位(Dirty bit):1位,标识页面是否已被修改。
- 引用位(Ref bit):1位,指示页面是否最近被访问,用于页替换算法。
- 访问权限(Access Rights):2位,标识页面的读/写权限。
- TLB标签(TLB Tag):18位,用于区分不同的虚拟地址。
- 计算方法:虚拟页号位数(26位)减去TLB索引的位数(在2路组相联情况下,为 \(\log_2(512 / 2) = 8\) 位),得到TLB标签的位数为 26 - 8 = 18位。
- 物理页号(PPN):22位,用于最终地址转换。
总TLB条目位数计算
综上,每个TLB条目所需的位数为:
\[ 1 \text{ (有效位)} + 1 \text{ (脏位)} + 1 \text{ (引用位)} + 2 \text{ (访问权限)} + 18 \text{ (TLB标签)} + 22 \text{ (物理页号)} = \textbf{45位} \]
进一步解释
这些位数确保了TLB可以有效地存储和快速查找地址转换信息。每个TLB条目存储的内容不仅包括虚拟页号和对应的物理页号,还包含了与内存管理相关的其他信息(如访问权限、是否修改等),以确保系统能够快速、安全地进行内存访问。