一、引子
之前文章讲解的是系统的虚拟内存,本章讲述这些硬件的架构和系统怎样统一管理这些硬件的。
二、物理内存模型
物理内存模型描述了计算机系统中的物理内存如何由操作系统组织和管理。它定义了物理内存如何划分为单元,如何寻址这些单元以及如何将它们映射到虚拟内存地址。物理内存模型对于确保高效和可靠的内存管理至关重要。
物理内存模型对操作系统管理内存分配、虚拟内存映射和内存访问模式产生重大影响。它会影响内存碎片化、缓存利用率和整体系统性能等因素。
2.1平坦内存模型(Flat Memory Model)
平坦内存模型,也称为线性内存模型,是一种简单的内存管理方式,在这种模型下,整个内存空间被视为一个连续的线性地址空间。每个地址直接对应物理内存中的一个字节,没有分段或分页的复杂性。
因为该内存模型的所有内存地址是一个连续的线性地址空间,因此Linux内核中,使用一个全局数组来管理这些物理内存页,并且内核中默认的配置是使用平坦内存模型。在Linux中最小分配的内存是4KB,所以即使是平坦内存模型,还是按页来管理内存的。
特点:
单一地址空间:所有程序和数据共享一个统一的地址空间,从地址0到最大地址。
无分段和分页:没有分段和分页机制,所有内存地址都是线性且连续的。
简单性:管理和编程简单,适用于内存需求较小且操作系统简单的系统。
优点:
简单易用:由于没有复杂的地址转换机制,编程和调试相对简单。
效率高:没有地址转换的开销,访问内存速度快。
低开销:硬件和软件开销较低,适合资源有限的系统。
缺点:
不灵活:不适合内存需求复杂的系统,难以进行内存保护和共享。
容易出错:程序错误可能会破坏整个系统内存,因为没有内存保护机制。
扩展性差:难以应对大规模内存需求,无法有效利用大内存。
2.2稀疏内存模型(Sparse Memory Model)
稀疏内存模型,也称为非连续内存模型,允许内存空间中存在大量未使用的地址区域(稀疏地址空间)。这种模型广泛用于需要大地址空间但实际使用内存较少的应用场景,如大规模数据处理、内存映射文件和某些高级编程语言的运行时系统。
在有多块非连续的物理内存时,在使用平坦内存模型的数组来初始化管理内存地址将会造成很大的内存浪费。稀疏内存模型是将物理内存划在宏观层面上分为一块一块的内存集合体,每个集合体使用一个节点来管理。内核在宏观上通过管理节点来间接的管理到每一个内存页。每个节点中管理的内存集合体也可以是不连续的,内核又将内存集合体分为多个连续内存块。在连续内存块中,内核就可以将其视为平坦内存模型来管理。
特点:
稀疏地址空间:地址空间中大部分区域未使用,仅在需要时分配实际的物理内存。
虚拟内存支持:通过虚拟内存机制,将实际需要的内存区域映射到物理内存,其余部分不占用物理内存。
按需分配:内存仅在访问时分配,减少了不必要的内存占用。
优点:
内存利用率高:由于仅在需要时分配内存,减少了物理内存的浪费。
支持大地址空间:可以处理非常大的地址空间,而不需要实际分配所有的物理内存。
灵活性:适合处理稀疏数据结构和大规模数据集,提供更大的灵活性。
缺点:
复杂的管理:需要操作系统和硬件支持虚拟内存和按需分配,增加了系统的复杂性。
可能的性能开销:按需分配和地址转换可能带来一定的性能开销,特别是在频繁访问新的内存区域时。
2.3补充
2.3.1 物理内存模型关系
平坦内存模型通过全局数组直接管理每一个内存页。
稀疏内存模型通过内存集合体的节点管理内存集合体,并且在内存集合体中又分出多个连续内存块。内存块和内存块中间,可以不连续。每一个连续内存块都可以视为平坦内存模型。
非连续内存模型是稀疏内存模型的一种简单形式,它不允许内存集合体中出现不连续的内存块,既将内存集合体视为平坦内存模型。但较新的内核代码已经不在做特殊区分。只是将平坦内存模型和稀疏内存模型使用宏隔开。
如图:
2.3.2 物理内存热插拔
从稀疏内存模型管理内存的方式不难看出,物理内存是否可以被系统使用,就看连续内存块能否管理到相应的内存。只要能让连续内存块管理或者不管理该内存,即可实现内存的动态加载或删除。简单来说:连续内存块和连续内存块中间本就可以是不连续的,只需让没有管理连续内存块的连续内存块节点指向一个内存区域就可以动态加载,或让正在管理连续内存块的连续内存块节点指向空就可以动态删除。
需要注意的是,因为内核态的虚拟地址空间中,有一段直接映射区,这块区域是和物理内存地址直接映射的关系,这些物理内存是无法被动态删除的。一块内存是否能被动态删除是内核在初始化时就决定的。
三、CPU和物理内存架构
在多处理器系统中,内存架构是指多个处理器如何访问和共享内存资源的机制。它对于系统性能和可扩展性至关重要。上面讲了物理内存模型,下面要阐述CPU是怎么访问这些物理内存的。
3.1一致性内存访问(Uniform Memory Access,UMA)
一致性内存访问,所有处理器都共享相同的物理内存,并且访问内存的速度和延迟是均匀的。这意味着每个处理器访问内存的时间是相同的,无论内存地址是什么。
特点:
统一内存访问时间:所有处理器对内存的访问时间一致。
共享内存架构:所有处理器共享相同的物理内存,没有本地和远程内存的区别。
对称多处理:UMA通常用于对称多处理(SMP)系统中,每个处理器有相同的访问权限和能力。
优点:
编程简单:由于访问内存的延迟一致,程序员不需要考虑不同内存访问速度的问题。
负载均衡:可以更容易地实现负载均衡,因为所有处理器访问内存的成本相同。
硬件简单:相对于非一致性内存访问(NUMA),UMA的硬件设计相对简单。
缺点:
可扩展性差:随着处理器数量增加,共享内存带宽成为瓶颈,系统性能难以线性扩展。
内存争用:所有处理器共享同一内存总线,容易出现内存争用问题,影响系统性能。
3.2非一致性内存访问(Non-Uniform Memory Access,NUMA)
非一致性内存访问,与一致性内存访问(UMA)相反。在NUMA架构中,每个处理器(或处理器组)有自己的本地内存(Local Memory),同时也可以访问其他处理器的远程内存(Remote Memory)。这种架构设计旨在提高大规模多处理器系统的可扩展性和性能。
特点:
本地和远程内存:每个处理器组(或节点)有自己的本地内存,访问速度比较快;同时可以访问其他处理器组的远程内存,速度较慢。
分布式内存架构:系统内存被分割成多个区域(或节点),每个节点由处理器组成,并拥有一部分物理内存。
非均匀访问时间:访问本地内存的延迟比访问远程内存的延迟低,因此访问时间不均匀。
优点:
提高扩展性:NUMA架构可以有效处理大型多处理器系统的内存访问和管理,避免了单一内存总线或互连网络的瓶颈。
减少内存争用:每个处理器组有自己的本地内存,减少了不同处理器之间因访问同一内存而产生的争用。
适应大规模并行工作负载:适合需要大量并行计算和高内存带宽的应用场景,如科学计算和大数据处理。
缺点:
复杂的编程模型:NUMA架构需要考虑内存分布和访问延迟的不均匀性,编程和优化相对复杂。
高成本:相对于UMA,NUMA系统通常更昂贵,因为需要更复杂的硬件互连和内存控制器。
远程访问性能差:访问远程内存的延迟较高,可能会影响特定类型的应用程序性能。
3.3其他架构
缓存一致性共享内存(CC-UMA): 每个处理器都有自己的本地缓存,但所有处理器共享一个全局一致性视图。这种架构结合了 UMA 和 NUMA 的优点,既能提供低延迟的本地访问,又能支持大规模扩展。
分布式共享内存(DSM): 物理内存分布在多个节点上,每个节点拥有一部分内存。处理器通过消息传递访问其他节点的内存。这种架构具有高度的可扩展性,但编程和调试更加复杂。
随着多处理器系统变得越来越复杂,内存架构也将继续发展。未来的趋势包括:
混合内存架构: 使用不同类型的内存架构来满足不同的需求,例如使用 NUMA 架构来满足对高性能的需求,使用 DSM 架构来满足对可扩展性的需求。
硬件支持的一致性模型: 硬件支持更强的一致性模型,以简化编程并提高性能。
新型内存技术: 使用新的内存技术,例如非易失性内存(NVM),来提高性能和降低功耗。