Linux x86_64 进程虚拟地址空间布局详解

完整虚拟地址空间分布图

┌─────────────────┬──────────────────────────────────────────────────────────┬─────────────────┐
│   地址范围      │                    内存区域描述                            │   权限/特征      │
├─────────────────┼──────────────────────────────────────────────────────────┼─────────────────┤
│0xFFFFFFFFFFFFFF │                      内核空间                            │                 │
│       FFF       │ ┌──────────────────────────────────────────────────────┐ │                 │
│       ↓         │ │         内核核心区域 (Kernel Core)                   │ │   r-x/rw-       │
│0xFFFFFFFF80000 │ │    内核TEXT/DATA/BSS段, 内核符号表, 内核堆栈等        │ │                 │
│       000       │ │                                                      │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFFFFFFF601 │ │                 VSYSCALL页结束                        │ │                 │
│       000       │ │                                                      │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFFFFFFFF600 │ │                 VSYSCALL页                           │ │   r-x (兼容)    │
│       000       │ │         (4KB, 已废弃但保留兼容性)                    │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFFFFFFF000 │ │               内核模块区域结束                        │ │                 │
│       000       │ │                                                      │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFFFFFFA0000 │ │               内核模块区域                           │ │   r-x/rw-       │
│       000       │ │        (Kernel Modules: .ko文件加载区域)             │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFFFFF00000 │ │                    保留区域                          │ │   ---           │
│       000       │ │                                                      │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFFFE800000  │ │                                                      │ │                 │
│       000       │ │                                                      │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFFE800000  │ │              CPU入口区域 (CPU Entry Area)            │ │   rw-           │
│       000       │ │       每CPU的GDT/IDT/TSS/入口栈/异常栈               │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFFFE000000  │ │                                                      │ │                 │
│       000       │ │                                                      │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFFE000000  │ │                固定映射区域 (Fixmap)                 │ │   根据用途      │
│       000       │ │    APIC映射, ACPI表, early_ioremap临时映射等         │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFFF9800000  │ │                                                      │ │                 │
│       000       │ │                                                      │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFF9800000  │ │               KASAN影子内存区域                       │ │   rw-           │
│       000       │ │       (仅在CONFIG_KASAN=y时存在)                    │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFFF9000000  │ │                                                      │ │                 │
│       000       │ │                                                      │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFF5800000  │ │                   空洞区域                            │ │   ---           │
│       000       │ │                                                      │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFFEA000000  │ │                                                      │ │                 │
│       000       │ │                                                      │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFEA000000  │ │           虚拟内存映射区域 (VMEMMAP)                  │ │   rw-           │
│       000       │ │     struct page数组映射 (稀疏内存模型支持)            │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFFE9000000  │ │                                                      │ │                 │
│       000       │ │                                                      │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFE8FFFFFFF │ │                vmalloc区域结束                        │ │                 │
│       FFF       │ │                                                      │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFFC9000000  │ │              vmalloc/ioremap区域                     │ │   rw-/根据映射  │
│       000       │ │  非连续物理内存的连续虚拟映射, 设备I/O内存映射        │ │                 │
│                 │ │  vmalloc(), vmap(), ioremap(), 持久化映射等          │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFFC8800000  │ │           直接物理内存映射区结束                      │ │                 │
│       000       │ │                                                      │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFF88800000  │ │         直接物理内存映射区 (Direct Mapping)           │ │   rw-           │
│       000       │ │   所有物理RAM的线性1:1映射 (虚拟地址=物理地址+偏移)    │ │                 │
│                 │ │   内核通过此区域访问物理内存, 支持64TB物理内存        │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0xFFFF88000000  │ │                    8TB空洞                           │ │   ---           │
│       000       │ │                                                      │ │                 │
│       ↓         │ │                                                      │ │                 │
│0xFFFF80000000  │ │                                                      │ │                 │
│       000       │ └──────────────────────────────────────────────────────┘ │                 │
├─────────────────┼──────────────────────────────────────────────────────────┼─────────────────┤
│0xFFFF80000000  │                      内核空间起始                        │                 │
│       000       │                                                        │                 │
│       ↓         │                                                        │                 │
│0x00008000000   │                   非规范地址区域                        │   硬件不支持     │
│       000       │              (Non-canonical Address)                  │                 │
│      ...        │               访问会产生#GP(通用保护)异常               │                 │
│       ↓         │                 硬件不支持此地址范围                    │                 │
│0x00007FFFFFFF   │                                                        │                 │
│       FFF       │                                                        │                 │
├─────────────────┼──────────────────────────────────────────────────────────┼─────────────────┤
│0x00007FFFFFFF   │                        用户空间                        │                 │
│       FFF       │ ┌──────────────────────────────────────────────────────┐ │                 │
│       ↓         │ │                  栈区域 (Stack)                      │ │   rw-           │
│0x00007F800000   │ │              ↓向下增长(向低地址)                     │ │                 │
│       000       │ │   函数调用栈帧、局部变量、函数参数、返回地址          │ │                 │
│      (约)       │ │            默认8MB大小限制                          │ │                 │
│                 │ │         地址随机化(ASLR)影响起始位置                 │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0x00007F800000   │ │                环境变量和参数                        │ │   r--           │
│       000       │ │              (Environment & Args)                   │ │                 │
│      (约)       │ │                  程序启动参数                        │ │                 │
│       ↓         │ │                                                      │ │                 │
│0x00007F000000   │ │                                                      │ │                 │
│       000       │ │                                                      │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0x00007F000000   │ │               内存映射区域 (mmap region)              │ │   根据映射类型  │
│       000       │ │          文件映射、匿名映射、共享内存                 │ │                 │
│      (约)       │ │              共享库(.so)加载区域                     │ │   r-x/rw-       │
│       ↓         │ │    libc.so, libpthread.so等动态链接库               │ │                 │
│vDSO随机位置      │ │         地址随机化(ASLR)影响加载位置                 │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│vDSO区域随机     │ │                   vDSO区域                           │ │   r-x           │
│      位置       │ │      Virtual Dynamic Shared Object                  │ │                 │
│     (~8KB)      │ │   快速系统调用: gettimeofday, clock_gettime等        │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│    program      │ │                  堆区域 (Heap)                       │ │   rw-           │
│     break       │ │               ↑向上增长(向高地址)                    │ │                 │
│       ↑         │ │        malloc/calloc/new等动态内存分配               │ │                 │
│   (动态边界)     │ │          通过brk/sbrk系统调用管理边界                │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│    BSS段结束     │ │             BSS段 (未初始化数据段)                   │ │   rw-           │
│       ↑         │ │        未初始化的全局变量和静态变量                  │ │                 │
│   DATA段结束     │ │              运行时自动清零                          │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│    DATA段结束    │ │             DATA段 (已初始化数据段)                  │ │   rw-           │
│       ↑         │ │        已初始化的全局变量和静态变量                  │ │                 │
│   TEXT段结束     │ │                                                      │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│   TEXT段结束     │ │              TEXT段 (代码段)                         │ │   r-x           │
│       ↑         │ │               程序机器指令                           │ │                 │
│0x00000040000   │ │    只读+可执行权限, 多进程可共享                     │ │                 │
│       000       │ │  包含: .text .rodata .plt .got等节                  │ │                 │
│      (默认)     │ │         (PIE启用时会随机化)                         │ │                 │
├─────────────────┼ ├──────────────────────────────────────────────────────┤ ├─────────────────┤
│0x00000001000   │ │                 空指针保护区域结束                    │ │                 │
│       000       │ │                                                      │ │                 │
│       ↓         │ │                                                      │ │                 │
│0x00000000000   │ │                 空指针保护区域                        │ │   ---           │
│       000       │ │           (0x0000 - 0x10000: 64KB)                 │ │   (不可访问)     │
└─────────────────┴─┴──────────────────────────────────────────────────────┴─┴─────────────────┘
                   │                      地址空间起始                      │                 


总虚拟地址空间: 256TB (48位有效地址)    |    页大小: 4KB (支持2MB/1GB大页)
用户空间大小: 128TB                   |    页表级数: 4级 (支持5级页表扩展)  
内核空间大小: 128TB                   |    地址随机化: ASLR/KASLR支持

详细地址范围对照表

区域名称起始地址结束地址大小增长方向权限用途简述
内核核心区域0xFFFFFFFF800000000xFFFFFFFFFFFFFFFF~2GB固定r-x/rw-内核代码数据
VSYSCALL页0xFFFFFFFFFF6000000xFFFFFFFFFF6010004KB固定r-x兼容旧系统调用
内核模块区0xFFFFFFFFA00000000xFFFFFFFFFF000000~1.5GB动态r-x/rw-内核模块加载
CPU入口区0xFFFFFE00000000000xFFFFFE8000000000512GB固定rw-每CPU数据结构
固定映射区0xFFFFFD00000000000xFFFFFE00000000001TB固定多样硬件寄存器映射
VMEMMAP0xFFFFEA00000000000xFFFFF20000000000128TB固定rw-page结构体数组
vmalloc区0xFFFFC900000000000xFFFFE8FFFFFFFFFF~32TB动态rw-非连续内存分配
直接映射区0xFFFF8880000000000xFFFFC87FFFFFFFFF64TB固定rw-物理内存线性映射
用户栈~0x7FFFFFFFFFFF向下8MB(默认)rw-函数调用栈
mmap区域~0x7F0000000000动态动态双向多样文件映射/共享库
vDSO~0x7FFF00000000~0x7FFF000020008KB固定r-x快速系统调用
堆区域BSS段后向上动态rw-动态内存分配
BSS段DATA段后固定编译时确定rw-未初始化全局变量
DATA段TEXT段后固定编译时确定rw-已初始化全局变量
TEXT段0x400000(默认)固定编译时确定r-x程序代码
NULL保护0x0000000000000x00000001000064KB空指针保护

用户空间详细说明 (0x0000000000000000 – 0x00007FFFFFFFFFFF)

1. 空指针保护区域 (0x0000000000000000 – 0x0000000000010000)

0x0000000000000000 - 0x0000000000010000  (64KB)
  • 权限: 无访问权限
  • 作用:
  • 防止空指针解引用攻击
  • 捕获野指针访问
  • NULL指针保护

2. TEXT段 (代码段)

默认起始地址: 0x0000000000400000 (4MB对齐)
PIE启用时会随机化
  • 权限: r-x (只读+可执行)
  • 内容:
  .text       - 程序指令
  .rodata     - 只读数据(字符串常量等)
  .eh_frame   - 异常处理信息
  .plt        - 程序链接表
  .got.plt    - 全局偏移表

3. DATA段 (已初始化数据)

  • 权限: rw- (可读写)
  • 内容:
  .data       - 已初始化全局变量
  .got        - 全局偏移表
  .dynamic    - 动态链接信息

4. BSS段 (未初始化数据)

  • 权限: rw- (可读写)
  • 特点:
  • 运行时由内核清零
  • 在可执行文件中不占用磁盘空间

5. 堆区域 (Heap)

起始地址: BSS段结束后,向上增长
管理: brk/sbrk系统调用
  • 分配器层次:
  用户程序 malloc/free
        ↓
  glibc malloc实现
        ↓  
  brk/mmap系统调用
        ↓
  内核内存管理
  • 内部结构:
  • 小块内存: 使用arena管理
  • 大块内存: 直接mmap分配

6. 内存映射区域 (Memory Mapping)

地址范围: 0x00007F0000000000附近 (ASLR随机化)
  • 用途:
  文件内存映射    - mmap(file)
  匿名内存映射    - mmap(ANON)
  共享内存       - shm_open + mmap
  动态链接库     - 共享对象(.so文件)

6.1 动态链接库区域

  • 常见库:
  /lib64/ld-linux-x86-64.so.2    - 动态链接器
  /lib64/libc.so.6               - C标准库
  /lib64/libpthread.so.0         - POSIX线程库
  /lib64/libm.so.6               - 数学库

7. 栈区域 (Stack)

默认大小: 8MB (可通过ulimit -s修改)
增长方向: 向低地址增长
起始地址: 接近0x00007FFFFFFFFFFF (ASLR随机化)
  • 栈帧结构:
  高地址 → 低地址方向:
  函数参数 → 返回地址 → 旧栈帧指针 → 局部变量

内核空间详细说明 (0xFFFF800000000000 – 0xFFFFFFFFFFFFFFFF)

1. 内核空间总体布局 (Linux 5.15)

// arch/x86/include/asm/page_64_types.h 和相关文件定义

#define __PAGE_OFFSET_BASE      _AC(0xffff888000000000, UL)
#define VMALLOC_START           _AC(0xffffc90000000000, UL)
#define VMALLOC_END             _AC(0xffffe8ffffffffff, UL)
#define VMEMMAP_START           _AC(0xffffea0000000000, UL)
#define CPU_ENTRY_AREA_BASE     _AC(0xfffffe0000000000, UL)
#define MODULES_VADDR           _AC(0xffffffffa0000000, UL)
#define MODULES_END             _AC(0xffffffffff000000, UL)

2. 直接物理内存映射区 (Direct Mapping of RAM)

地址范围: 0xFFFF888000000000 - 0xFFFFC87FFFFFFFFF (64TB)
  • 映射关系:
  虚拟地址 = 物理地址 + 0xFFFF888000000000
  物理地址 = 虚拟地址 - 0xFFFF888000000000
  • 作用:
  • 内核可以直接访问所有物理RAM
  • page结构体通过该区域访问
  • DMA一致性内存分配
  • 快速的物理-虚拟地址转换

3. vmalloc区域 (Non-contiguous Memory)

地址范围: 0xFFFFC90000000000 - 0xFFFFE8FFFFFFFFFF (~32TB)
  • 用途:
  vmalloc()     - 分配虚拟连续但物理不连续的内存
  vmap()        - 映射已存在的页面到虚拟地址
  ioremap()     - 映射设备I/O内存
  • 子区域:
  一般vmalloc区域
  ioremap区域 (设备内存映射)
  持久化映射区域

4. 虚拟内存映射区 (Virtual Memory Map)

地址范围: 0xFFFFEA0000000000 - 0xFFFFF57FFFFFFFFF
  • 作用:
  • 稀疏内存模型 (SPARSEMEM) 的page结构体数组
  • 每个物理页面对应一个struct page
  • 支持内存热插拔

5. kasan影子内存区域 (KASAN Shadow Memory)

地址范围: 0xFFFFF90000000000 - 0xFFFFF97FFFFFFFFF (仅在KASAN启用时)
  • 作用:
  • Kernel Address SANitizer影子内存
  • 用于检测内核内存访问错误

6. CPU入口区域 (CPU Entry Area)

地址范围: 0xFFFFFE0000000000 - 0xFFFFFE7FFFFFFFFF
  • 内容:
  每CPU的GDT (全局描述符表)
  每CPU的IDT (中断描述符表)  
  每CPU的TSS (任务状态段)
  每CPU的入口栈
  异常栈

7. 固定映射区域 (Fixmap)

地址范围: 0xFFFFFEA00000000 附近
  • 用途:
  Local APIC映射
  IO APIC映射
  ACPI表映射
  VDSO映射
  VSYSCALL映射
  early_ioremap()临时映射

8. 每CPU变量区域 (Per-CPU Variables)

地址范围: 动态分配,通常在vmalloc区域
  • 作用:
  DEFINE_PER_CPU(int, example_var);
  per_cpu(example_var, cpu_id);

9. 内核模块区域 (Kernel Modules)

地址范围: 0xFFFFFFFFA0000000 - 0xFFFFFFFFFF000000 (~1.5GB)
  • 内容:
  内核模块(.ko文件)的代码和数据
  模块的符号表
  模块的依赖关系信息

10. 内核核心区域 (Kernel Core)

地址范围: 0xFFFFFFFF80000000 - 0xFFFFFFFFFFFFFFF
  • 内容:
  内核TEXT段    - 内核代码
  内核DATA段    - 内核已初始化数据  
  内核BSS段     - 内核未初始化数据
  初始化数据    - __init段,启动后释放
  只读数据段    - 常量、字符串等

特殊内存区域详解

1. VSYSCALL区域 (已废弃但兼容)

地址: 0xffffffffff600000 - 0xffffffffff601000 (4KB)
  • 内容: gettimeofday, time, getcpu等系统调用
  • 状态: 已被vDSO替代,仅保留兼容性

2. vDSO区域 (Virtual Dynamic Shared Object)

位置: 用户栈下方随机位置
大小: 通常8KB
  • 作用:
  快速系统调用实现:
  - clock_gettime()
  - gettimeofday()  
  - time()
  - getcpu()

3. 内存保护机制

3.1 SMEP (Supervisor Mode Execution Prevention)

  • 防止内核执行用户空间代码

3.2 SMAP (Supervisor Mode Access Prevention)

  • 防止内核访问用户空间数据

3.3 KASLR (Kernel Address Space Layout Randomization)

# 内核启动参数控制
nokaslr          # 禁用内核ASLR
kaslr            # 启用内核ASLR (默认)

4. 内存限制和配置

# 查看内核内存布局
cat /proc/iomem
cat /proc/vmallocinfo
cat /proc/slabinfo

# 内核配置选项
CONFIG_RANDOMIZE_BASE=y        # KASLR
CONFIG_X86_5LEVEL=y           # 5级页表支持
CONFIG_SPARSEMEM_VMEMMAP=y    # 虚拟内存映射

5. 页表层次结构 (5级页表)

虚拟地址位分解 (48位有效地址):
[47:39] PGD索引 (Page Global Directory)
[38:30] P4D索引 (Page 4th Directory) 
[29:21] PUD索引 (Page Upper Directory)
[20:12] PMD索引 (Page Middle Directory)  
[11:0]  PTE索引 (Page Table Entry) + 页内偏移

这个内存布局为Linux系统提供了安全、高效的虚拟内存管理,支持现代硬件特性和安全机制。

本文版权归原作者zhaofujian所有,采用 CC BY-NC-ND 4.0 协议进行许可,转载请注明出处。

发表评论