内存布局与映射关系
虚拟内存的布局划分与其对应的物理内存之间的映射关系
32位系统
32位系统最大可以访问内存地址范围为0 ~ 4G
,这4G内存的被分为用户空间内存
和内核空间内存
- 用户空间:
0x0000_0000 ~ 0xBFFF_FFFF
(0G ~ 3G) - 内核空间:
0xC000_0000 ~ 0xFFFF_FFFF
(3G ~ 4G)
虚拟地址划分
Linux下32位寻址空间的大致分布(虚拟内存):
虚拟地址与物理地址之间的关系
虚拟内存和物理内存的转换通过MMU
硬件来实现
32位CPU可以访问的寻址范围只有4G,因此如果物理内存大于4G时,应该如何处理?
目前在linux系统中可以通过PAE可以支持物理内存超过4G的访问,但是此时CPU也必须支持PAE功能,这部分后面有机会研究了详细说明。
在之前一直以为物理内存超过4G与高端内存有关,而实际上高端内存的产生至于虚拟内存地址范围有关,与物理内存无关。
高端内存
High Memory: 解决的问题是在32位CPU下虚拟机地址空间不足
带来的问题。
原因:
在内核中我们要进行频繁的虚拟地址(VA)和物理地址(PA)操作,在这种情况下,如何高效的进行VA to PA的转换就很重要。可是如果按照多级页表路径查找,内存访问开销就比较大,因此采用了另一种简单的”fix-mapping”思路,将0xc000 0000~0xffff ffff
虚拟地址直接映射到0x0000 0000~0x3fff ffff
,也就是将虚拟地址空间最高1G全部映射到物理地址空间最低的1G上,这样VA与PA之间就存在3G的固定偏移,这样PA=VA-3G。
这样使用简单高效,但是也存在局限性,就是在内核空间只能使用1G的物理内存。但是随着技术的发展1G大小的内核空间已经无法满足内核的使用,因此需要将内核空间增大,有人提议重新划分用户空间和内核空间的比例,比如不按照3:1,使用2.5:1.5等,但由于一些特殊场景(比如用户空间使用的内存非常多)会使得用户态运行效率降低,同时带来一些非对其问题,因此也不是一个很好的办法。
最后就引入了高端内存
,将内核空间的1G地址,分为两部分,一部分同样采用fix-mapping
,另一部分用来dynamic mapping
,以X86为例,实际中的做法是,0xC000 0000-0xF7FF FFFF
的896MB用作fix-mapping
,0xF800 0000-0xFFFF FFFF
的128MB用作dynamic-mapping
,前者仍然对应于物理地址的0x0000 0000-0x37FF FFFF
(只不过部分要优先分配给DMA);后者就是所谓的high memory
。
实际上high memory
还被划分为了3个区域,一部分用于vmalloc分配虚拟地址上连续的内存,一部分用于较长期的动态映射(persistent kernel mappings),还有一部分用于编译时可以直接分配物理地址的高端固定映射(fixmaps)
- 虚拟内存中连续、但物理内存中不连续的内存区,可以在
vmalloc区域
分配。该机制通常用于用户过程,内核自身会试图尽力避免非连续的物理地址。内核通常会成功,因为大部分大的内存块都在启动时分配给内核,那时内存的碎片尚不严重。但在已经运行了很长时间的系统上,在内核需要物理内存时,就可能出现可用空间不连续的情况。此类情况,主要出现在动态加载模块时。 持久映射
用于将高端内存域中的非持久页映射到内核中固定映射
是与物理地址空间中的固定页关联的虚拟地址空间项,但具体关联的页帧可以自由选择。它与通过固定公式与物理内存关联的直接映射页相反,虚拟固定映射地址与物理内存位置之间的关联可以自行定义,关联建立后内核总是会注意到的。
在linux中高端内存的大小,可以通过启动参数进行指定:
1 | highmem=nn[KMG] [KNL,BOOT] forces the highmem zone to have an exact |
Documentation/admin-guide/kernel-parameters.txt
在64位系统中,不存在这个问题,因此64位系统的内存划分不存在高端内存
(High Memory)
PAE
- linux内存管理之PAE(物理地址扩展)解决内存大于4G的问题
虚拟内存空间与进程地址空间
64位系统
环境:arm64CPU,linux系统
64bit内存地址可用空间为0x0000 0000 0000 0000 ~ 0xFFFF FFFF FFFF FFFF
64位CPU的寻址分三种:
ARM64架构的处理器采用的是48位
的物理寻址方式。用户空间和内核空间最大支持256TB的地址空间。
1 | config ARM64_PA_BITS_48 |
- 内核空间 :0xFFFF 0000 0000 0000 ~ 0xFFFF FFFF FFFF FFFF (256TB)
- 非规范区 :0x0000 FFFF FFFF FFFF ~ 0xFFFF 0000 0000 0000 (未使用)
- 用户空间 :0x0000 0000 0000 0000 ~ 0x0000 FFFF FFFF FFFF (256TB)
48位寻址划分
1 | AArch64 Linux memory layout with 4KB pages + 4 levels (48-bit):: |
参考
- linux的高端内存是什么?
- Documentation/arm64/memory.rst
- Documentation/x86/x86_64/mm.rst