Linux内核分析之内存管理-01

韩乔落

第1章:概述

基于 Linux 6.12.38 源码,涵盖物理内存与虚拟内存管理的核心机制

学习目标: 理解 Linux 内存管理的核心概念、架构和数据流


1.1 基础概念

1.1.1 物理地址 vs 虚拟地址

物理地址 (Physical Address):

  • 内存硬件上的实际地址
  • CPU 通过地址总线直接访问
  • 受物理内存大小限制

虚拟地址 (Virtual Address):

  • 程序看到的地址空间
  • 由 MMU 转换为物理地址
  • 可以远大于物理内存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌─────────────────────────────────────────────────────────────────┐
│ 地址转换过程示意 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 程序使用虚拟地址: │
│ 0x7fff12345678 │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ MMU │ │
│ │ (地址转换) │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ 物理地址: 0x87654321 │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 物理内存 │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

1.1.2 页式存储管理

Linux 使用页式存储管理,将内存划分为固定大小的块:

术语 大小 (x86_64) 描述
页 (Page) 4KB 内存管理的基本单位
巨页 (Huge Page) 2MB/1GB 提高性能,减少 TLB 压力
PTE (Page Table Entry) 8 bytes 页表项,存储一个页的映射

为什么需要分页?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
不分页的问题:
┌─────────────────────────────────────────────────────────────────┐
│ 问题 1: 碎片化 │
│ ├── 程序 A 需要连续 1MB 内存 │
│ ├── 物理内存有足够空间但不连续 │
│ └── 分配失败 │
│ │
│ 问题 2: 内存保护 │
│ ├── 进程 A 可以访问进程 B 的内存 │
│ └── 安全隐患 │
│ │
│ 问题 3: 地址空间限制 │
│ ├── 32 位系统最多 4GB 地址空间 │
│ └── 无法运行大型程序 │
└─────────────────────────────────────────────────────────────────┘

分页的优势:
┌─────────────────────────────────────────────────────────────────┐
│ 优势 1: 消除碎片化 │
│ ├── 虚拟地址连续即可 │
│ ├── 物理页可以分散 │
│ └── 提高内存利用率 │
│ │
│ 优势 2: 内存隔离 │
│ ├── 每个进程独立的页表 │
│ ├── 硬件强制权限检查 │
│ └── 安全可靠 │
│ │
│ 优势 3: 虚拟地址空间 │
│ ├── 64 位系统支持 256TB 地址空间 │
│ ├── 只需加载需要的页面 (按需分页) │
│ └── 节省物理内存 │
└─────────────────────────────────────────────────────────────────┘

1.1.3 用户空间 vs 内核空间

Linux 将虚拟地址空间划分为两部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
┌─────────────────────────────────────────────────────────────────┐
│ 64 位系统虚拟地址空间布局 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 0xFFFFFFFFFFFFFFFF (用户空间最大地址) │
│ │ │
│ │ 用户空间 (User Space) │
│ │ ┌───────────────────────────┐ │
│ │ │ │ │
│ │ │ 程序代码、数据、堆、栈 │ │
│ │ │ 约 128TB (默认) │ │
│ │ │ │ │
│ │ └───────────────────────────┘ │
│ │ │
│ 0x00007FFFFFFFFFFF │
│ │ │
│ ────────┼──────────────── (分界线) │
│ │ │
│ 0xFFFF800000000000 │
│ │ │
│ │ 内核空间 (Kernel Space) │
│ │ ┌───────────────────────────┐ │
│ │ │ │ │
│ │ │ 内核代码、数据、结构体 │ │
│ │ │ 直接映射区、vmalloc区等 │ │
│ │ │ │ │
│ │ └───────────────────────────┘ │
│ │ │
│ 0xFFFF800000000000 │
│ │
└─────────────────────────────────────────────────────────────────┘

用户空间特性:

  • 每个进程独立
  • 使用较低的虚拟地址
  • 通过系统调用访问内核

内核空间特性:

  • 所有进程共享
  • 使用较高的虚拟地址
  • 受保护,用户无法直接访问

1.2 内存管理子系统职责

核心功能

物理内存管理

  • 页面的分配、释放、回收
  • 通过伙伴系统 (Buddy System) 管理物理内存
  • 支持 NUMA 架构的多节点内存管理

虚拟内存管理

  • 地址空间的创建、映射、保护
  • 每个进程有独立的虚拟地址空间
  • 实现进程间的内存隔离

页表管理

  • 多级页表的创建、更新、遍历
  • 实现虚拟地址到物理地址的转换 (MMU)
  • TLB (Translation Lookaside Buffer) 管理

缺页处理

  • 按需加载 (Demand Paging)
  • 写时复制 (Copy-on-Write)
  • 延迟分配策略提高内存利用率

页面回收

  • LRU (Least Recently Used) 算法
  • 交换 (Swap) 机制
  • 在内存不足时回收页面

内存共享

  • 进程间共享内存
  • 写时复制节省物理内存

1.2 内存管理架构

1.2.1 子系统组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
┌────────────────────────────────────────────────────────────────┐
│ 内存管理子系统 │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ 页面分配器 │ │ Slab/Slub │ │ 页表管理 │ │
│ │ Buddy System│ │ Allocator │ │ Paging │ │
│ │ │ │ │ │ │ │
│ │ - 物理页面 │ │ - 小对象分配│ │ - 多级页表 │ │
│ │ - 伙伴算法 │ │ - 内核缓存 │ │ - TLB 管理 │ │
│ │ - 迁移类型 │ │ - kmalloc │ │ - 缺页处理 │ │
│ └──────────────┘ └──────────────┘ └─────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ 页面回收 │ │ 缺页处理 │ │ 内存映射 │ │
│ │ Page Reclaim│ │ Page Fault │ │ Memory Map │ │
│ │ │ │ │ │ │ │
│ │ - LRU 管理 │ │ - 匿名页 │ │ - mmap │ │
│ │ - kswapd │ │ - 文件页 │ │ - mprotect │ │
│ │ - 直接回收 │ │ - COW │ │ - munmap │ │
│ │ - 多代 LRU │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └─────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ 交换机制 │ │ 内存压缩 │ │ 内存 cgroup │ │
│ │ Swap │ │ Compaction │ │ Memcg │ │
│ │ │ │ │ │ │ │
│ │ - 交换分区 │ │ - 页面迁移 │ │ - 限制内存 │ │
│ │ - 交换缓存 │ │ - 碎片整理 │ │ - 统计使用 │ │
│ │ - zswap │ │ - kcompactd │ │ - OOM 控制 │ │
│ └──────────────┘ └──────────────┘ └─────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘

1.2.2 内存管理全景关联图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
┌─────────────────────────────────────────────────────────────────────┐
│ Linux 6.12 内存管理全景图 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ 用户进程 │ │
│ │ malloc/mmap │ │
│ └──────┬───────┘ │
│ │ 系统调用 │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 内核空间 │ │
│ ├──────────────────────────────────────────────────────────────┤ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ VMA管理 │────▶│ 页表管理 │────▶│ 缺页处理 │ │ │
│ │ │ mmap/munmap │ │ PGD/PUD/PMD │ │ do_anonymous │ │ │
│ │ │ (ch06,11) │ │ /PTE (ch05) │ │ _page (ch09) │ │ │
│ │ └─────────────┘ └──────┬──────┘ └──────┬──────┘ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ 物理内存分配器 (Buddy System) │ │ │
│ │ │ free_area[order][migratetype] │ │ │
│ │ │ (ch03) │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ ▲ │ │
│ │ │ │ │
│ │ ┌─────────────┐ ┌─────────────────────────────────┐ │ │
│ │ │ 页面分配 │◀────│ 页面回收 │ │ │
│ │ │ alloc_pages │ │ kswapd/direct reclaim │ │ │
│ │ │ (ch07) │ │ (ch10) │ │ │
│ │ └─────────────┘ └─────────────────────────────────┘ │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 物理内存层次结构 │ │
│ │ Node (pglist_data) → Zone → Page → Slab Object │ │
│ │ (ch02) (ch02) (ch02) (ch08) │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

图例说明:

  • ──► : 数据流向
  • ──▲ : 反向依赖
  • (chXX) : 对应章节

1.3 关键源码位置

功能 目录 主要文件
核心内存管理 mm/ memory.c, page_alloc.c
页表管理 mm/ pgtable.c, fault.c, mmap.c
Slab 分配器 mm/ slab.c, slub.c, slob.c
页面回收 mm/ vmscan.c
交换机制 mm/ swap.c, swap_state.c, swapfile.c
内存压缩 mm/ compaction.c
页迁移 mm/ migrate.c
页缓存 mm/ filemap.c, page-io.c
匿名内存 mm/ mprotect.c, mlock.c
内存 cgroup mm/ memcontrol.c
KSM mm/ ksm.c
内核页表 arch/*/mm/ pgtable.c, init.c
头文件 include/linux/ mm.h, mm_types.h, mmzone.h, pgtable.h, gfp.h
体系相关 arch/*/mm/ 各种体系结构相关文件

1.4 相关数据结构概览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* 物理内存管理 */
struct page; // 物理页面描述符
struct folio; // 多页复合页描述符 (Linux 5.15+)
struct zone; // 内存区域管理
struct pglist_data; // 节点管理 (NUMA)
struct lruvec; // LRU 向量

/* 虚拟内存管理 */
struct vm_area_struct; // 虚拟内存区域 (VMA)
struct mm_struct; // 内存描述符
struct vm_struct; // 内核虚拟内存区域

/* 页表管理 */
struct ptdesc; // 页表描述符 (Linux 6.6+)

/* 文件映射 */
struct address_space; // 地址空间 (页缓存)

/* 内存控制 */
struct mem_cgroup; // 内存控制组

/* 对象分配 */
struct kmem_cache; // Slab 缓存

/* 页面回收 */
struct reclaim_state; // 回收状态
struct shrinker; // 缓存收缩器

/* 交换 */
struct swap_info_struct; // 交换分区信息
  • Title: Linux内核分析之内存管理-01
  • Author: 韩乔落
  • Created at : 2026-01-20 21:37:24
  • Updated at : 2026-02-24 14:05:10
  • Link: https://jelasin.github.io/2026/01/20/Linux内核分析之内存管理-01/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments