操作系统-内存管理 - 4
2024-02-28 09:20:13 0 举报
AI智能生成
内核虚拟内存空间
作者其他创作
大纲/内容
32位内核虚拟内存空间布局
分支主题
子主题
区域划分
1、直接映射区
概念
在总共大小 1G 的内核虚拟内存空间中,位于最前边有一块 896M 大小的区域,我们称之为直接映射区或者线性映射区,地址范围为 3G -- 3G + 896m
这块 896M 大小的区域称为直接映射区或者线性映射区,是因为这块连续的虚拟内存地址会映射到 0 - 896M 这块连续的物理内存上
内核态虚拟内存空间的前 896M 区域是直接映射到物理内存中的前 896M 区域中的,直接映射区中的映射关系是一比一映射。映射关系是固定的不会改变
映射图
分支主题
存放内容
前 1M 已经在系统启动的时候被系统占用
1M 之后的物理内存存放的是内核代码段,数据段,BSS 段(这些信息起初存放在 ELF格式的二进制文件中,在系统启动的时候被加载进内存)
进程被创建完毕之后,在内核运行的过程中,会涉及内核栈的分配
内核会为每个进程分配一个固定大小的内核栈(一般是两个页大小,依赖具体的体系结构),每个进程的整个调用链必须放在自己的内核栈中,内核栈也是分配在直接映射区
内核栈容量小而且是固定,溢出危害非常巨大,它会直接悄无声息的覆盖相邻内存区域中的数据,破坏数据
场景
使用 fork 系统调用创建进程的时候,内核会创建一系列进程相关的描述符
进程的核心数据结构 task_struct
进程的内存空间描述符 mm_struct
虚拟内存区域描述符 vm_area_struct
这些进程相关的数据结构也会存放在物理内存前 896M 的这段区域中,也会被直接映射至内核态虚拟内存空间中的 3G -- 3G + 896m 这段直接映射区域中
分支主题
ZONE_DMA
在 X86 体系结构下,ISA 总线的 DMA (直接内存存取)控制器,只能对内存的前16M 进行寻址
这就导致了 ISA 设备不能在整个 32 位地址空间中执行 DMA,只能使用物理内存的前 16M 进行 DMA 操作
直接映射区的前 16M 专门让内核用来为 DMA 分配内存,这块 16M 大小的内存区域我们称之为 ZONE_DMA
用于 DMA 的内存必须从 ZONE_DMA 区域中分配
ZONE_NORMAL
而直接映射区中剩下的部分也就是从 16M 到 896M(不包含 896M)这段区域,我们称之为 ZONE_NORMAL
ZONE_NORMAL 由于也是属于直接映射区的一部分,对应的物理内存 16M 到 896M 这段区域也是被直接映射至内核态虚拟内存空间中的 3G + 16M 到 3G + 896M 这段虚拟内存上
2、ZONE_HIGHMEM高端内存
概念
物理内存 896M 以上的区域被内核划分为 ZONE_HIGHMEM 区域,我们称之为高端内存
物理内存假设为 4G,高端内存区域为 4G - 896M = 3200M,那么这块 3200M 大小的 ZONE_HIGHMEM 区域该如何映射到内核虚拟内存空间中?
内核虚拟内存空间中的前 896M 虚拟内存已经被直接映射区所占用,而在 32 体系结构下内核虚拟内存空间总共也就 1G 的大小,这样一来内核剩余可用的虚拟内存空间就变为了 1G - 896M = 128M
物理内存中 3200M 大小的 ZONE_HIGHMEM 区域无法继续通过直接映射的方式映射到这 128M 大小的虚拟内存空间中
物理内存中的 ZONE_HIGHMEM 区域就只能采用动态映射的方式映射到 128M 大小的内核虚拟内存空间中
只能动态的一部分一部分的分批映射,先映射正在使用的这部分,使用完毕解除映射,接着映射其他部分
128M内核虚拟内存空间如何布局
内核虚拟内存空间中的 3G + 896M 这块地址在内核中定义为 high_memory,high_memory 往上有一段 8M 大小的内存空洞。空洞范围为:high_memory 到 VMALLOC_START
分支主题
VMALLOC_START 定义在内核源码 /arch/x86/include/asm/pgtable_32_areas.h 文件中
分支主题
区域划分
1、内存空洞
空洞范围为:high_memory 到 VMALLOC_START
VMALLOC_START 定义在内核源码 /arch/x86/include/asm/pgtable_32_areas.h 文件中
分支主题
2、vmalloc动态映射区
VMALLOC_START 到 VMALLOC_END 之间的这块区域成为动态映射区
分支主题
采用动态映射的方式映射物理内存中的高端内存
分支主题
这块动态映射区域内核使用vmalloc进行内存分配
vmalloc分配的内存在虚拟内存上连续,物理内存不连续。通过页表来建立物理内存和虚拟内存之间的映射关系
从而可以将不连续的物理内存映射到连续的虚拟内存上
由于 vmalloc 获得的物理内存页是不连续的,因此它只能将这些物理内存页一个一个地进行映射,在性能开销上会比直接映射大得多
3、永久映射区
PKMAP_BASE 到 FIXADDR_START 之间的这段空间称为永久映射区。
LAST_PKMAP 表示永久映射区可以映射的页数限制。
分支主题
内核的这段虚拟地址空间中允许建立与物理高端内存的长期映射关系。比如内核通过 alloc_pages() 函数在物理内存的高端内存中申请获取到的物理内存页,这些物理内存页可以通过调用 kmap 映射到永久映射区中
分支主题
4、固定映射区
固定映射区,区域范围为:FIXADDR_START 到 FIXADDR_TOP
分支主题
在固定映射区中的虚拟内存地址可以自由映射到物理内存的高端地址上
分支主题
与动态映射区以及永久映射区不同的是,在固定映射区中虚拟地址是固定的,而被映射的物理地址是可以改变的。
有些虚拟地址在编译的时候就固定下来了,是在内核启动过程中被确定的,而这些虚拟地址对应的物理地址不是固定的
固定虚拟地址的好处是它相当于一个指针常量(常量的值在编译时确定),指向物理地址,如果虚拟地址不固定,则相当于一个指针变量
5、临时映射区
作用
作为缓存页临时映射内核空间的区域
3、整体布局
分支主题
64位体系内核虚拟空间布局
1、整体布局
分支主题
2、用户空间
分支主题
3、内核空间
分支主题
区块
1、8T空洞
2、64T直接映射区
这个区域中的虚拟内存地址减去 PAGE_OFFSET 就直接得到了物理内存地址
分支主题
3、32T的vmalloc映射区
类似用户空间中的堆,内核在这里使用 vmalloc 系统调用申请内存
4、1T的虚拟内存映射区
用于存放物理页面的描述符 struct page 结构用来表示物理内存页
5、从 __START_KERNEL_map 开始是512M 的区域
用于存放内核代码段、全局变量、BSS 等
对应到物理内存开始的位置,减去 __START_KERNEL_map 就能得到物理内存的地址
0 条评论
下一页