Linux-64位系统内存分配(Linux-64位系统内存分配)
Linux-64位系统内存分配(Linux-64位系统内存分配)2.页面映射有四级1.线性地址48位2-MByte 页面在x86_64CPU架构中页面线性地址映射称为IA32-e模式,这里只考虑4k页面大小时的映射根据上图可以看出线性地址映射的内容有
Linux-64位系统内存分配在Intel体系结构的CPU中,现代操作系统如Linux都采用内存保护模式来管理内存。我们看Linux内核中的内存管理相关内容时,会遇到一个基本问题:普通用户程序中的地址是如何转换到内存上的物理地址的?IA-32架构的CPU规定地址映射过程是逻辑地址–>线性地址–>物理地址。Linux既然能在Intel架构的CPU上运行,就要遵守这个规定,那么Linux又是如何进行地址映射的
映射流程简述分段的存在更多就是为了兼容性,所以在 x86-64 下的 64位程序该功能近似于 bypass。处理器默认 CS, DS, ES, SS的段基址为 0,所以我们下面就不讨论逻辑地址到线性地址的转换了,因为基址为0,经过运算后线性地址和逻辑地址是一样的。
分页过程会将 48-bit 的线性地址转换为 52-bit 的物理地址 可以看出虽然是 64bit 的操作系统但在处理器层面并没有提供 2^64 大小的访问范围。48-bit 线性地址可以有以下 3 种映射分配
4-KByte 页面
2-MByte 页面
在x86_64CPU架构中页面线性地址映射称为IA32-e模式,这里只考虑4k页面大小时的映射
根据上图可以看出线性地址映射的内容有
1.线性地址48位
2.页面映射有四级
48位线性地址分成五段,每段宽度分别为9、9、9、9、12。映射的方法为页表查找。
pgd、pud、pmd、pte各占了9位,加上12位的页内index,共用了48位。即可管理的地址空间为2^48=256T。而在32位地址模式时,该值仅为2^32=4G
另外64位地址时支持的物理内存最大为64T,见e820.c中MAX_ARCH_PFN的定义:
# define MAX_ARCH_PFN MAXMEM>>PAGE_SHIFT
其中MAXMEM为2^46,PAGE_SHIFT为12。
而在32位地址时最大支持的物理内存为64G(开启PAE选项)。
3.CR3寄存器保存最高一级表的起始物理地址
4.每个表项大小都为8byte
地址空间
64位地址时将0x0000 0000 0000 0000 – 0x0000 7fff ffff f000这128T地址用于用户空间。参见定义:
#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE),注意这里还减去了一个页面的大小做为保护。
而0xffff 8000 0000 0000以上为系统空间地址。注意:该地址前4个都是f,这是因为目前实际上只用了64位地址中的48位(高16位是没有用的),而从地址0x0000 7fff ffff ffff到0xffff 8000 0000 0000中间是一个巨大的空洞,是为以后的扩展预留的。
而真正的系统空间的起始地址,是从0xffff 8800 0000 0000开始的,参见:
#define __PAGE_OFFSET _AC(0xffff 8800 0000 0000 UL)
而32位地址时系统空间的起始地址为0xC000 0000。
另外0xffff 8800 0000 0000 – 0xffff c7ff ffff ffff这64T直接和物理内存进行映射,0xffff c900 0000 0000 – 0xffff e8ff ffff ffff这32T用于vmalloc/ioremap的地址空间。
而32位地址空间时,当物理内存大于896M时,由于地址空间的限制,内核只会将0~896M的地址进行映射,而896M以上的空间用做一些固定映射和vmalloc/ioremap。而64位地址时是将所有物理内存都进行映射。