嵌入式Linux中文站

linux内存管理之物理内存相关知识


Linux内核采用页式存储管理,进程的地址空间被划分成固定大小的“页面”(page),物理内存同样被分为与页面大小相同的“页帧“(page frame),由MMU在运行时将虚拟地址“映射”成某个物理内存页帧上的地址,MMU一般内嵌在CPU上。

1 NUMA(Non Uniform Memory Access)

在现代计算机,特别是在多核的CPU环境中,CPU访问内存的速度与两者之间的距离有关,导致访问不同内存区域的时间可能不同。如下图,是系统中有2个CPU(可以超过2个CPU)时,NUMA内存访问 模型。

下图是Intel Nehalem(Xeon E5xxx系列)架构中NUMA内存访问模型。每个CPU下面都有物理内存,两个CPU之间通过QPI总线通信。黑色箭头表示访问本地CPU下面的物理内存,绿色箭头为访问另外CPU下的物理内存。本地CPU访问其他CPU下面内存时,数据要 通过QPI总线传输。显然访问本地内存速度最快,访问其他CPU下面的内存速度较慢。这就是NUMA的由来。

下面两个图分别是Nehalem架构下,本地内存访问和远端内存访问模型。



2 页面和虚拟内存(Paging and Virtual Memory)

当打开Intel CPU页面机制时,线性地址空间就划分成页面,虚拟地址的页面然后映射 到物理页面。当Linux使用页面机制时,对上层应用程序是透明的。即Intel CPU就是这么实现的,采用段页式机制,所有运行在Intel CPU上的OS都要遵守页面机制,包括Windows、 Linux都是如此。
下图是x86/x86_64架构中,页面大小为4K时,页面属性。

下面表为页面属性(Page Table Entry)各字段含义。这些字段包括线性地址对应的物理页面是否存在、页面是否可读写、是用户模式还是系统模式、页面是否为脏等。这些属性 在Linux内核实现中都会用到。

为了便于理解页面属性的作用,我们来看一个示例。如系统有两个进程i和j,内核可以设置该进程使用的物理页面属性,如进程对某些页面只能读,而不能写;对某些页面可读可 写。这样既可以

2.1 PAE(Physical Address Extensions)
在x86 CPU中,只有32位地址总线,也就意味着只有4G地址空间。为了实现在32位系 统中使用更多的物理内存,Intel CPU提供了PAE(Physical Address Extensions)机制, 这样可以使用超过4G物理内存。
PAE机制的打开,需要设置CR0、CR4控制寄存器和IA32_EFER MSR寄存器。设置值 为CR0.PG = 1,CR4.PAE = 1和IA32_EFER.LME = 0。但PAE机制打开后,MMU会将32 位线性地址转换为52位物理地址。尽管物理地址是52位(4PB),但线性地址仍然为32位, 即进程可使用的物理内存不超过4GB。

2.2 PSE(Page Size Extensions)
前面提到x86/x86_64 CPU中提供的是段页式机制,也介绍了页面。页面大小虽然是固 定的,但x86/x86_64 CPU支持两种页面大小4KB和4MB。大多数情况下OS内核使用的是 4KB页面,但系统中多数进程使用内存较大时,如每次申请至少4MB,则使用4MB页面较为 合适。当控制寄存器CR4.PSE = 1时,页面大小是4MB。

2.3 TLB(Translation Lookaside Buffers)
CPU将逻辑地址转换为物理地址,需要多次访问物理内存,从内存中读取页面目录表、页面表。若有4级映射,从内存读取地址映射表的次数更多。这个过程相对CPU运算能力而言,是非常耗时的。
CPU可以将线性地址映射信息保存在TLB中,即TLB保存着线性地址与物理页面的对应关系,这样CPU下次访问该线性地址时,直接可以从TLB中找到对应的物理页面,不再需要线性地址到物理地址的繁琐映射过程,大大加快找到物理页面的速度。
我们对CPU的Cache非常熟悉,一般用缓存内存数据的指令。TLB也是一种Cache,也是在集成在CPU内部,只是它保存地址映射关系,不是数据或指令。线性地址映射时,每次都首先会从TLB中查找,若命中,则直接读出物理页面地址,若未命中,再进行页式地址映射。

本文永久更新链接:http://embeddedlinux.org.cn/emb-linux/kernel-driver/201709/22-7435.html



分享:

评论