1. Linux物理内存三级架构
对于内存管理,Linux采用了与具体体系架构不相关的设计模型,实现了良好的可伸缩性。它主要由内存节点node、内存区域zone和物理页框page三级架构组成。
• 内存节点node
内存节点node是计算机系统中对物理内存的一种描述方法,一个总线主设备访问位于同一个节点中的任意内存单元所花的代价相同,而访问任意两个不同节点中的内存单元所花的代价不同。在一致存储结构(Uniform Memory Architecture,简称UMA)计算机系统中只有一个节点,而在非一致性存储结构(NUMA)计算机系统中有多个节点。Linux内核中使用数据结构pg_data_t来表示内存节点node。如常用的ARM架构为UMA架构。
• 内存区域zone
内存区域位于同一个内存节点之内,由于各种原因它们的用途和使用方法并不一样。如基于IA32体系结构的个人计算机系统中,由于历史原因使得ISA设备只能使用最低16MB来进行DMA传输。又如,由于Linux内核采用
• 物理页框page
2. Linux虚拟内存三级页表
Linux虚拟内存三级管理由以下三级组成:
• PGD: Page Global Directory (页目录)
• PMD: Page Middle Directory (页目录)
• PTE: Page Table Entry (页表项)
每一级有以下三个关键描述宏:
• SHIFT
• SIZE
• MASK
如页的对应描述为:
数据结构定义如下:
2.1 Page Directory (PGD and PMD)
每个进程有它自己的PGD( Page Global Directory),它是一个物理页,并包含一个pgd_t数组。其定义见<asm/page.h>。 进程的pgd_t数据见 task_struct -> mm_struct -> pgd_t * pgd;
ARM架构的PGD和PMD的定义如下<arch/arm/include/asm/pgtable.h>:
虚拟地址MASK和SIZE宏图:
2.2 Page Table Entry
PTEs, PMDs和PGDs分别由pte_t, pmd_t 和pgd_t来描述。为了存储保护位,pgprot_t被定义,它拥有相关的flags并经常被存储在page table entry低位(lower bits),其具体的存储方式依赖于CPU架构。
每个pte_t指向一个物理页的地址,并且所有的地址都是页对齐的。因此在32位地址中有PAGE_SHIFT(12)位是空闲的,它可以为PTE的状态位。
PTE的保护和状态位如下图所示:
2.3 如何通过3级页表访问物理内存
为了通过PGD、PMD和PTE访问物理内存,其相关宏在asm/pgtable.h中定义。
• pgd_offset
根据当前虚拟地址和当前进程的mm_struct获取pgd项的宏定义如下:
• pmd_offset 根据通过pgd_offset获取的pgd 项和虚拟地址,获取相关的pmd项(即pte表的起始地址)
• pte_offset
根据通过pmd_offset获取的pmd项和虚拟地址,获取相关的pte项(即物理页的起始地址)
其示意图如下图所示:
2.4 根据虚拟地址获取物理页的示例代码
根据虚拟地址获取物理页的示例代码详见<mm/memory.c中的函数follow_page>。