完整虚拟地址空间分布图
┌─────────────────┬──────────────────────────────────────────────────────────┬─────────────────┐
│ 地址范围 │ 内存区域描述 │ 权限/特征 │
├─────────────────┼──────────────────────────────────────────────────────────┼─────────────────┤
│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支持
详细地址范围对照表
区域名称 | 起始地址 | 结束地址 | 大小 | 增长方向 | 权限 | 用途简述 |
---|---|---|---|---|---|---|
内核核心区域 | 0xFFFFFFFF80000000 | 0xFFFFFFFFFFFFFFFF | ~2GB | 固定 | r-x/rw- | 内核代码数据 |
VSYSCALL页 | 0xFFFFFFFFFF600000 | 0xFFFFFFFFFF601000 | 4KB | 固定 | r-x | 兼容旧系统调用 |
内核模块区 | 0xFFFFFFFFA0000000 | 0xFFFFFFFFFF000000 | ~1.5GB | 动态 | r-x/rw- | 内核模块加载 |
CPU入口区 | 0xFFFFFE0000000000 | 0xFFFFFE8000000000 | 512GB | 固定 | rw- | 每CPU数据结构 |
固定映射区 | 0xFFFFFD0000000000 | 0xFFFFFE0000000000 | 1TB | 固定 | 多样 | 硬件寄存器映射 |
VMEMMAP | 0xFFFFEA0000000000 | 0xFFFFF20000000000 | 128TB | 固定 | rw- | page结构体数组 |
vmalloc区 | 0xFFFFC90000000000 | 0xFFFFE8FFFFFFFFFF | ~32TB | 动态 | rw- | 非连续内存分配 |
直接映射区 | 0xFFFF888000000000 | 0xFFFFC87FFFFFFFFF | 64TB | 固定 | rw- | 物理内存线性映射 |
用户栈 | ~0x7FFFFFFFFFFF | 向下 | 8MB(默认) | ↓ | rw- | 函数调用栈 |
mmap区域 | ~0x7F0000000000 | 动态 | 动态 | 双向 | 多样 | 文件映射/共享库 |
vDSO | ~0x7FFF00000000 | ~0x7FFF00002000 | 8KB | 固定 | r-x | 快速系统调用 |
堆区域 | BSS段后 | 向上 | 动态 | ↑ | rw- | 动态内存分配 |
BSS段 | DATA段后 | 固定 | 编译时确定 | – | rw- | 未初始化全局变量 |
DATA段 | TEXT段后 | 固定 | 编译时确定 | – | rw- | 已初始化全局变量 |
TEXT段 | 0x400000(默认) | 固定 | 编译时确定 | – | r-x | 程序代码 |
NULL保护 | 0x000000000000 | 0x000000010000 | 64KB | – | — | 空指针保护 |
用户空间详细说明 (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 协议进行许可,转载请注明出处。