深入Linux内核架构—内存管理(二)

一、(N)UMA 模型中的内存组织

Linux支持的各种不同体系结构在内存管理方面差别很大。由于内核的明智设计,以及某些情况下插入的兼容层,这些差别被隐藏起来了。按照先前讨论过的,一个主要的问题是页表中不同数目的间接层。另一个关键是NUMA和UMA系统的划分

内核对一致和非一致内存访问系统使用相同的数据结构,针对各种不同形式的内存布局,各个算法几乎没有什么差别。在UMA系统上,只使用一个NUMA结点来管理整个系统内存。而内存管理的其他部分则相信它们是在处理一个伪NUMA系统。

1、概述

在讲解内核中用于组织内存的数据结构之前,需要先定义几个概念。首先考虑NUMA系统。图3-3给出了下述内存划分的图示。

首先,内存划分为结点。每个结点关联到系统中的一个处理器,在内核中表示为pg_data_t的实例。

各个结点又划分为内存域,是内存的进一步细分。例如,对可用于 DMA操作的内存区是有限制的。只有前16 MB适用,还有一个高端内存区域无法直接映射。在二者之间是通用的普通内存区。因此一个结点最多由3个内存域组成。内核引入了下列常量来区分它们。

内核引入了下列常量来枚举系统中的所有内存域:

linux/mmzone.h

ZONE_DMA标记适合DMA的内存域。该区域的长度依赖于处理器类型。在IA-32计算机上,一般的限制是16 MB,这是由ISA(工业标准体系结构)设备强加的边界。但更现代的计算机也可能受这一限制的影响。

ZONE_DMA32标记使用32位地址按字寻址、适合DMA的内存域。在32位计算机上,本内存域是空的,即长度为0 MB。

ZONE_NORMAL标记可直接映射到内核段的普通内存域。这是在所有体系结构上保证都会存在的唯一内存域,但无法保证该地址范围对应了实际的物理内存。

ZONE_HIGHMEM标记超出内核段的物理内存。

根据编译时的配置,可能无需考虑某些内存域。例如在64位系统中,并不需要高端内存域。如果支持只能访问4 GB以下内存的32位外设,才需要DMA32内存域。

内核定义一个伪内存域ZONE_MOVABLE,在防止物理内存碎片的机制中需要使用该内存域。

MAX_NR_ZONES充当结束标记,在内核想要迭代系统中的所有内存域时,会用到该常量。

各个内存域都关联一个数组,用来组织属于该内存域的物理内存页(内核中称为页帧)。对每个页帧,都分配一个struct page实例以及所需的管理数据。

各个内存结点保存在一个单链表中,供内核遍历。

出于性能考虑,在为进程分配内存时,内核总是试图在当前运行的CPU相关联的NUMA结点上进行。但这并不总是可行的,例如,该结点的内存可能已经用尽。对此类情况, 每个结点都提供了一个备用列表(借助于struct zonelist)。该列表包含了其他结点(和相关的内存域),可用于代替当前结点分配内存。列表项的位置越靠后,就越不适合分配。

2、数据结构

已经解释用于内存管理的各种数据结构之间的关系,现在分别讲解各个数据结构。

1)结点管理

pg_data_t是用于表示结点的基本元素,定义如下:

linux/mmzone.h

node_zones是一个数组,包含结点中各内存域的数据结构。

node_zonelists指定备用结点及其内存域的列表,以便在当前结点没有可用空间时,在备用结点分配内存。

结点中不同内存域的数目保存在nr_zones。

node_mem_map用于描述结点的所有物理内存页。它包含结点中所有内存域的页。

在系统启动期间,内存管理子系统初始化之前,内核也需要使用内存(另外,还必须保留部分内存用于初始化内存管理子系统)。为解决这个问题,内核使用自举内存分配器( boot memory allocator)。bdata指向自举内存分配器数据结构的实例。

node_start_pfn是该NUMA结点第一个页帧的逻辑编号。系统中所有结点的页帧是依次编号的,每个页帧的号码都是全局唯一的。

node_start_pfn在UMA系统中总是0,因为其中只有一个结点,因此其第一个页帧编号总是0。

node_present_pages结点中页帧的数目,node_spanned_pages该结点以页帧为单位计算的长度。二者的值不一定相同,因为结点中可能有一些空洞,并不对应真正的页帧。

node_id是全局结点ID。系统中的NUMA结点都从0开始编号。

kswapd_wait是交换守护进程( swap daemon)的等待队列,在将页帧换出结点时会用到。kswapd指向负责该结点的交换守护进程的task_struct。kswapd_max_order用于页交换子系统的实现,用来定义需要释放的区域的长度。

图3-3给出结点及其包含的内存域之间的关联,以及备用列表,这些是通过结点数据结构起始处的几个数组建立的。数组的数据保存在结点数据结构之中。

结点的内存域保存在node_zones。该数组总是有3个项,即使结点没有那么多内存域,也是如此。如果不足3个,则其余的数组项用0填充。

结点状态管理

如果系统中结点多于一个,内核会维护一个位图,用以提供各个结点的状态信息。状态是用位掩码指定的,可使用下列值:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值