一,概述
Linux内核一般将处理器的虚拟地址空间划分为两个部分。底部比较大的部分用于用户进程,顶部专用于内核。虽然(在两个用户进程之间的)上下文切换期间会改变下半部分,但是虚拟地址空间的内核部分总是保持不变。
有两种类型计算机,分别以不同的方法管理物理内存。
(1) UMA计算机 (一致内存访问,uniform memory access) 将可用内存以连续方式组织起来。SMP系统中的每个处理器访问各个内存区都是同样快。
(2) NUMA计算机(非一致性内存访问, non-uniform memory access) 总是多处理器计算机。系统的各个CPU都有本地内存,可支持特别快速非访问。各个处理器之间通过总线连接起来,以支持对其他CPU的本地内存的访问,当然比访问本地内存慢些。
二、(N)UMA模型中的内存组织
UMA和NUMA使用相同的数据结构。在UMA系统中,只使用一个NUMA结点来管理整个系统内存,从而内存管理的其他部分则相信它们是在处理一个伪NUMA系统。
(1) 首先,内存划分为结点。每个结点关联到系统中一个处理器。内核中表示为pg_data_t的实例。
(2) 各个结点又划分成内存域,是内存的进一步划分。
(3) 各个内存域都关联了一个数组,用来组织属于改内存域的物理内存页(页帧)。每个页帧,分配一个struct page实例以及所需的管理数据。
各个内存结点保存在一个单链表中,供内核遍历。
内存域(ZONE)有不同的类型,主要划分为三个大的区域ZONE_DMA,ZONE_NOMAL,ZONE_HIGHMEM。
FLATMEM模型
按照历史演进,物理内存管理共有FLATMEM、DISCONTIGMEM以及SPRARSEMEM模型。这里主要介绍一下FLATMEM模型。
flat模型实质是将整块物理内存划分到一个数组中进行管理,整个物理内存划分到一个数组mem_map数组中实现一个平滑管理。整个物理内存划分成页进行管理,mem_map的数组单位是struct page,物理内存管理的最小颗粒度是page。
linux内核代码关于mem_map的初始化部分:
都是通过调用free_are_init_core()函数,初始化mem_map数组。在free_are_init_core函数中首先根据zones_size大小计算共有多少个实际物理页。然后从bootmem(系统引导区)申请 (totalpages + 1)*sizeof(struct page)实际物理空间。在mem_map数组建立起来之前,整个系统内存管理是有bootmem(系统引导区)进行管理,申请内存页是从系统引导区中申请。mem_map数组建立之后,kernel会把物理内存管理权由bootmem转入到mem_map进行管理。代码如下:
/*
* Set up the zone data structures:
* - mark all pages reserved
* - mark all memory queues empty
* - clear the memory bitmaps
*/
void __init free_area_init_core(int nid, pg_data_t