linux内核那些事之虚拟空间划分

linux虚拟空间划分

一般操作系统为了提供远超实际物理内存的空间,提供了虚拟空间概念。即虽然实际系统中的物理内存比较小,但是通过将整个空间进行一个虚拟抽象能够为每个进程提供远远超过实际物理内存的空间,这样就给每个进程提供了一个假象 :“每个进程都拥有整个系统的空间”。虚拟空间的好处就不必多说,一般操作系统的课程上都是着重讲解。linux内核中将整个虚拟空间划分为内核空间和用户空间,每个进程的用户空间是相互隔离,而内核空间是每个进程都相互共享。X86 64系统的地址空间划分在Documentation\x86\x86_64\mm.rst文档中有说明,x86 64位空间划分有两种形式如下:

linux内核那些事之虚拟空间划分

两种形式主要是因为page table 分别为4级 或 5级数划分不同,x86 64系统下默认方式为 4级划分方式。用户空间和内核空间为分开管理,在两个空间之间有一段常常的hole 空间用于预留。

内核空间划分 

linux将内核空间按照不同的使用用途,分别划分成不同段进行管理,Documentation\x86\x86_64\mm.rst文档中详细描述了内核空间,以 4 level page table为例:

linux内核那些事之虚拟空间划分

  • 0xffff800000000000 ~0xffff87ffffffffff :即可以作为guard hole 以防止内核空间越界,又可以作为 hypervisor 使用
  • 0x0xfff880000000000 ~ 0xffff887fffffffff:local descriptor table(LDT)局部描述表存放空间
  • 0xffff888000000000 ~0xffffc87fffffffff:物理内存直接映射区,大小为64TB 即物理内存小于64TB的都是直接映射到该区域,由于目前暂时还很少有大于64TB的物理内存,故在64位系统下暂时没有high zone的划分。
  • 0xffffc88000000000 ~0xffffc8ffffffffff:空洞
  • 0xffffc90000000000 ~0xffffe8ffffffffff :vmalloc或者ioremap 空间
  • 0xffffe90000000000 ~0xffffe9ffffffffff: 空洞
  • 0xffffea0000000000 ~0xffffeaffffffffff: vmemp存放地址。
  • 0xffffeb0000000000 ~0xffffebffffffffff: 空洞
  • 0xffffec0000000000 ~ 0xfffffbffffffffff: KASAN使用
  • 0xfffffc0000000000 ~ 0xfffffdffffffffff:空洞
  • 0xfffffe0000000000 ~ 0xfffffe7fffffffff :cpu_entry_area 映射,关于cpu_entry_area解释,查到了下面一个解释,(水平有限还是没有理解,做个记录https://unix.stackexchange.com/questions/476768/what-is-cpu-entry-area):

cpu_entry_area contains all the data and code needed to allow the CPU to hand control over to the kernel. When KPTI is enabled, only that part of the kernel is mapped when user-space is running. You can see its definition in arch/x86/include/asm/cpu_entry_area.h: it contains

  • the GDT;
  • the entry stack;
  • the TSS;
  • a set of trampolines;
  • the exception stacks;
  • debug stores and buffers.
  • 0xfffffe8000000000 ~ 0xfffffeffffffffff 空洞
  • 0xffffff0000000000 ~ 0xffffff7fffffffff :%esp fixup stacks 。
  • 0xffffff8000000000 ~0xffffffeeffffffff:空洞
  • 0xffffffef00000000 ~0x fffffffeffffffff:EFI 映射区域
  • ... ...  

64位系统内,划分太多不再一一详细描述,上述每划分一段意味着都需要单独做空间分配等一系列管理动作,所以内核空间被切分成一段段进行管理。以后再详细描述各个内核空间管理。

用户空间划分

linux 的用户空间划分主要有以下几个部分:

linux内核那些事之虚拟空间划分

地址从0x00007fffffffffff ~0x0000000000000000从高地址向地址依次划分如下:

  • stack:栈 空间 从高地址向地地址增长
  • mapping are: map 映射区域,主要是调用系统调用maping
  • heap:堆划分区域,主要调用malloc 申请的区域
  • BSS: 程序BSS 段
  • Data: 程序数据段
  • CODE:程序代码段

用户空间中 由程序中经常分配和使用的区域主要是mapping映射区和 heap 堆区域。 stack 区域在程序运行由系统加载和使用。BSS,Data 以及代码段大小由程序编译后都已经固定,在程序运行前由加载器加载到各自区域。

内核和用户空间的各自管理方法不同,需要分别看待,再分析内核代码之前需要首先树立这样一个观念 便于从整理理解内核对整个空间管理。

上一篇:目标检测加速策略分析


下一篇:ThreadLocal 应用及源码分析