首页 > 代码库 > Linux 内核开发 - 内存管理

Linux 内核开发 - 内存管理

1.1什么是内存管理

内存管理是对计算机内存进行分配和使用的技术。内存管理主要存在于多任务的操作系统中,由于内存资源极其有限,需要在不同的任务之间共享内存,内存管理的存在就是要高效、快速的非配内存,并在适当的时候回收和释放内存,以保各个任务正常的执行。最常见的内存管理机制有:段式内存管理和页式内存管理。

1.2内存中的地址

早期的16位计算中,寄存器的位宽只有16位,为了能访问到1M Bit的内存空间,CPU就采用了分段的方式来管理内存,将1M的内存分为若干个逻辑段,每个逻辑段的起始地址必须是16的整数倍,每个逻辑段最大的访问空间为64K。 

1) 段基地址

将物理地址分为64K Bit 为单位的多个段,由于最后4位总是0,所以段的起始地址被右移4位后保存,需要计算实际的物理地址时再左移四位。

2) 逻辑地址(段内偏移地址)

逻辑地址地分段后段内偏移量。

3) 线性地址

线性地址代表了计算机的地址访问能力,代表了一个非物理的实体地址。是逻辑地址到物理地址变换之间的中间层。

在段式管理中,线性地址 段内基地址 逻辑地址。

4) 虚拟地址

虚拟地址的概念主要出现在虚拟内存技术中,它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),所以在某种情况下被称为线性地址。

5) 物理地址

实际物理存储器的地址,是地址转换的最终结果。

PS: 对于16位机来说,他的实际物理地址是20位,线性地址和物理地址是相同的所以线性地址到物理地址之间是一一对应的。

1.3 段式管理(32CPU)

x8632位机型有“实模式”与“保护模式”两种,在“实模式”下段的使用方式与16位机时一致的,但是在“保护模式”下,段寄存器被称为段选择器(segment selector),它存储的是段描述符(segment descriptor),段描述符记录了该段的基地址、权限等信息,段基地址+逻辑地址 可以转换成线性地址。

段式管理的优点:能够根据实际的代码,从用户的角度(程序员)的角度将代码分成多个逻辑段,比如数据段、代码段、堆栈段。段大小可变,利于保护数据、方便内存共享。

 

1.4 页式管理

页式管理是将线性地址划分为固定长度的管理单元,通常是4K大小,对32位计算机来说就划分了2^20个也,以二级的页式内存管理机制来说,线性地址被分为三部分

l 页目录地址:22~31 (10)

l 页表地址:12~21(10)

l 页内偏移量:0~11(共12位)

系统会为每个进程的页目录位置,通过线性地址的最高10位找到页表的起始地址,再通过中间10位找到页的起始地址,最后通过低12位找到页内偏移量,最终计算出物理地址。

 

1.5 Linux 的内存管理模式

Linux 是一个跨平台的操作系统,为了能支持Intel 的段式管理方式,它采用了段式 页式管理机制,不过Linux 仅仅是有限度的使用段式管理方式,因为Linux 系统中每个段的基地址都是0,所以 逻辑地址线性地址,逻辑地址转换成线性地址时一一对应。Linux 的这种处理方式不仅简化了内核,也为移植到不支持段式管理方式的平台上提供了方便。

更严格的说,Linux 采用了页式管理模式,不过因为不同的平台的页级数不一致,Linux 2.6.29使用了四级的页式管理结构来兼容不同页级数的CPU。这四级分别为:

页全局目录(Page Global Directory) pgd

页上级目录(Page Upper Directory)pud

页中间目录(Page Middle Directory)pmd

页表(Page Table Entry)pte


Linux 内核开发 - 内存管理