操作系统物理内存的组织形式

简介: 【2月更文挑战第12天】

由于物理地址是连续的,页也是连续的,每个页大小也是一样的。因而对于任何一个地址,只要直接除一下每页的大小,很容易直接算出在哪一页。每个页有一个结构 struct page 表示,这个结构也是放在一个数组里面,这样根据页号,很容易通过下标找到相应的 struct page 结构。


如果是这样,整个物理内存的布局就非常简单、易管理,这就是最经典的平坦内存模型(Flat Memory Model)。


在这种模式下,CPU 也会有多个,在总线的一侧。所有的内存条组成一大片内存,在总线的另一侧,所有的 CPU 访问内存都要过总线,而且距离都是一样的,这种模式称为 SMP(Symmetric multiprocessing),即对称多处理器。当然,它也有一个显著的缺点,就是总线会成为瓶颈,因为数据都要走它。

image.png

为了提高性能和可扩展性,后来有了一种更高级的模式,NUMA(Non-uniform memory access),非一致内存访问。在这种模式下,内存不是一整块。每个 CPU 都有自己的本地内存,CPU 访问本地内存不用过总线,因而速度要快很多,每个 CPU 和内存在一起,称为一个 NUMA 节点。但是,在本地内存不足的情况下,每个 CPU 都可以去另外的 NUMA 节点申请内存,这个时候访问延时就会比较长。


这样,内存被分成了多个节点,每个节点再被分成一个一个的页面。由于页需要全局唯一定位,页还是需要有全局唯一的页号的。但是由于物理内存不是连起来的了,页号也就不再连续了。于是内存模型就变成了非连续内存模型,管理起来就复杂一些。


这里需要指出的是,NUMA 往往是非连续内存模型。而非连续内存模型不一定就是 NUMA,有时候一大片内存的情况下,也会有物理内存地址不连续的情况。


当前的主流场景,NUMA 方式。我们首先要能够表示 NUMA 节点的概念,于是有了下面这个结构 typedef struct pglist_data pg_data_t,它里面有以下的成员变量:

  • 每一个节点都有自己的 ID:node_id;
  • node_mem_map 就是这个节点的 struct page 数组,用于描述这个节点里面的所有的页;
  • node_start_pfn 是这个节点的起始页号;
  • node_spanned_pages 是这个节点中包含不连续的物理内存地址的页面数;
  • node_present_pages 是真正可用的物理页面的数目。


ZONE_DMA 是指可用于作 DMA(Direct Memory Access,直接内存存取)的内存。DMA 是这样一种机制:要把外设的数据读入内存或把内存的数据传送到外设,原来都要通过 CPU 控制完成,但是这会占用 CPU,影响 CPU 处理其他事情,所以有了 DMA 模式。CPU 只需向 DMA 控制器下达指令,让 DMA 控制器来处理数据的传送,数据传送完毕再把信息反馈给 CPU,这样就可以解放 CPU。


对于 64 位系统,有两个 DMA 区域。除了上面说的 ZONE_DMA,还有 ZONE_DMA32。在这里你大概理解 DMA 的原理就可以,不必纠结,我们后面会讲 DMA 的机制。


ZONE_NORMAL 是直接映射区,就是上一节讲的,从物理内存到虚拟内存的内核区域,通过加上一个常量直接映射。


ZONE_HIGHMEM 是高端内存区,就是上一节讲的,对于 32 位系统来说超过 896M 的地方,对于 64 位没必要有的一段区域。


ZONE_MOVABLE 是可移动区域,通过将物理内存划分为可移动分配区域和不可移动分配区域来避免内存碎片。


为了让 CPU 快速访问段描述符,在 CPU 里面有段描述符缓存。CPU 访问这个缓存的速度比内存快得多。同样对于页面来讲,也是这样的。如果一个页被加载到 CPU 高速缓存里面,这就是一个热页(Hot Page),CPU 读起来速度会快很多,如果没有就是冷页(Cold Page)。由于每个 CPU 都有自己的高速缓存,因而 per_cpu_pageset 也是每个 CPU 一个。


物理内存的基本单位,页的数据结构 struct page。这是一个特别复杂的结构,里面有很多的 union,union 结构是在 C 语言中被用于同一块内存根据情况保存不同类型数据的一种方式。这里之所以用了 union,是因为一个物理页面使用模式有多种。


第一种模式,要用就用一整页。这一整页的内存,或者直接和虚拟地址空间建立映射关系,我们把这种称为匿名页(Anonymous Page)。或者用于关联一个文件,然后再和虚拟地址空间建立映射关系,这样的文件,我们称为内存映射文件(Memory-mapped File)。


如果某一页是这种使用模式,则会使用 union 中的以下变量:

  • struct address_space *mapping 就是用于内存映射,如果是匿名页,最低位为 1;如果是映射文件,最低位为 0;
  • pgoff_t index 是在映射区的偏移量;
  • atomic_t _mapcount,每个进程都有自己的页表,这里指有多少个页表项指向了这个页;
  • struct list_head lru 表示这一页应该在一个链表上,例如这个页面被换出,就在换出页的链表中;
  • compound 相关的变量用于复合页(Compound Page),就是将物理上连续的两个或多个页看成一个独立的大页。


第二种模式,仅需分配小块内存。有时候,我们不需要一下子分配这么多的内存,例如分配一个 task_struct 结构,只需要分配小块的内存,去存储这个进程描述结构的对象。为了满足对这种小内存块的需要,Linux 系统采用了一种被称为 slab allocator 的技术,用于分配称为 slab 的一小块内存。它的基本原理是从内存管理模块申请一整块页,然后划分成多个小块的存储池,用复杂的队列来维护这些小块的状态(状态包括:被分配了 / 被放回池子 / 应该被回收)。


对于要分配比较大的内存,例如到分配页级别的,可以使用伙伴系统(Buddy System)。


Linux 中的内存管理的“页”大小为 4KB。把所有的空闲页分组为 11 个页块链表,每个块链表分别包含很多个大小的页块,有 1、2、4、8、16、32、64、128、256、512 和 1024 个连续页的页块。最大可以申请 1024 个连续页,对应 4MB 大小的连续内存。每个页块的第一个页的物理地址是该页块大小的整数倍。

image.png

如果有多个 CPU,那就有多个节点。每个节点用 struct pglist_data 表示,放在一个数组里面。


每个节点分为多个区域,每个区域用 struct zone 表示,也放在一个数组里面。每个区域分为多个页。


为了方便分配,空闲页放在 struct free_area 里面,使用伙伴系统进行管理和分配,每一页用 struct page 表示。


image.png



相关文章
|
5天前
|
算法 程序员 调度
深入理解操作系统的内存管理机制
【5月更文挑战第9天】 在现代计算机系统中,操作系统的内存管理是一个至关重要的部分,它直接影响到系统的性能和稳定性。本文将深入探讨操作系统的内存管理机制,包括物理内存的管理、虚拟内存的概念和应用,以及内存分配和回收的策略。通过对这些内容的深入理解,我们可以更好地理解操作系统的工作原理,提高我们的编程效率和质量。
|
2天前
|
算法 安全 程序员
深入理解操作系统的内存管理机制
【5月更文挑战第18天】 在现代计算领域,操作系统的内存管理是确保系统高效稳定运行的关键。本文将详细探讨操作系统内存管理的核心概念、技术及其实现细节。通过分析虚拟内存、物理内存、分页、分段以及内存分配策略等要素,我们揭示了操作系统如何优化内存使用,保证安全性和提供多任务支持。此外,文中还将评估现代操作系统面临的内存管理挑战,如碎片化、内存泄露和虚拟化技术的应用。
|
2天前
|
算法 程序员 内存技术
深入理解操作系统内存管理:原理与实践
【5月更文挑战第18天】 在现代计算机系统中,操作系统扮演着关键角色,其中内存管理作为其核心功能之一,保障了系统资源的高效利用和程序的顺利运行。本文旨在探讨操作系统内存管理的基本原理及其在实际中的应用,涉及物理内存的组织、虚拟内存技术的实现以及内存分配策略等关键技术点。通过分析不同内存管理机制的优势与局限,我们将对操作系统如何协调多任务环境下的内存使用有更深刻的认识。
|
2天前
|
存储 算法 安全
深入理解操作系统的虚拟内存管理
【5月更文挑战第18天】在现代操作系统中,虚拟内存管理是一项核心功能,它允许系统使用有限的物理内存来模拟出看似无限的地址空间。本文将详细探讨虚拟内存的基本概念、工作原理及其在操作系统中的应用。我们将从虚拟内存的定义出发,解析其背后的关键技术如分页、分段和请求调页机制,并讨论其在提高系统性能和安全性方面的重要性。通过具体示例和案例分析,本文旨在为读者提供一个清晰的虚拟内存管理知识框架。
|
2天前
|
算法
深入理解操作系统的内存管理
【5月更文挑战第18天】 在现代计算机系统中,操作系统扮演着至关重要的角色,尤其在内存管理方面。本文将深入探讨操作系统内存管理的核心原理与技术,包括虚拟内存、分页机制、以及内存分配策略等。通过对这些概念的细致剖析,读者将获得对操作系统如何处理内存申请、分配、回收和优化的深刻理解。文章不仅涉及理论解释,还将介绍一些实际案例,帮助读者将这些理论知识应用于实践。
|
2天前
|
存储 缓存 算法
探索现代操作系统中的虚拟内存管理
【5月更文挑战第18天】 在当代计算机系统中,虚拟内存技术是支撑大型应用程序与多任务环境的关键。通过抽象物理硬件细节,它允许每个运行的程序仿佛拥有独立的、连续的地址空间。本文深入分析了虚拟内存的核心机制,包括分页、分段和请求分页调度,并讨论了它们如何提升系统的稳定性、安全性及效率。同时,文章还探讨了虚拟内存带来的性能问题及其优化策略,如页面置换算法和缓存技术。
10 4
|
3天前
|
存储 缓存 算法
深入理解操作系统内存管理:原理与实践
【5月更文挑战第17天】 本文旨在探讨操作系统中的内存管理机制,通过分析其核心原理及提供实际应用场景,帮助读者深化对操作系统内存管理的认识。文章首先介绍内存管理的基础知识,然后详细阐述连续分配与非连续分配策略,接着讨论分页和分段机制,并探索虚拟内存技术如何使得内存管理更加高效。此外,文中还将涉及内存优化技巧以及现代操作系统中内存管理面临的挑战。
|
3天前
|
算法
深入理解操作系统的内存管理
【5月更文挑战第17天】 在现代计算机系统中,操作系统扮演着资源管理者的角色,其内存管理机制对于系统性能和稳定性至关重要。本文将探讨操作系统内存管理的关键技术,包括虚拟内存、分页、分段以及内存分配策略,旨在提供一个全面的视角来理解操作系统如何高效地管理有限的物理内存资源。通过对这些技术的剖析,我们可以更好地理解操作系统的内部工作原理,并评估不同内存管理策略对系统性能的影响。
|
3天前
|
存储 算法 程序员
操作系统(11)----内存管理5
操作系统(11)----内存管理
10 1
操作系统(11)----内存管理5
|
3天前
|
存储 缓存 算法
操作系统(11)----内存管理4
操作系统(11)----内存管理
12 0