目录
内存管理是 Linux 操作系统内核最核心的功能之一。理解它不仅能帮助我们编写高效的 C/C++ 程序,还能在排查内存泄漏、优化系统性能、调优容器或服务器配置时发挥巨大作用。
一、什么是内存管理?
内存管理是操作系统管理内存资源的机制,包括:
-
分配 / 回收 内存
-
虚拟地址到物理地址映射
-
内存保护和隔离
-
交换空间(Swap)策略
-
缓存管理与页面回写
二、Linux 内存模型总览
Linux 将物理内存视为一个线性的地址空间,并在其上实现了虚拟内存机制。
常见术语:
-
物理内存:实际硬件上的 RAM。
-
虚拟内存:每个进程看到的独立内存空间,由内核统一映射到物理内存。
-
页(Page):Linux 内存管理的最小单位,通常是 4KB。
三、虚拟内存 vs 物理内存
Linux 使用 虚拟内存机制(Virtual Memory) 来隔离进程:
特性 | 虚拟内存 | 物理内存 |
---|---|---|
对象 | 每个进程独立空间 | 系统统一管理的 RAM |
可见性 | 进程私有 | 所有进程共享 |
地址空间大小 | 4GB(x86)/128TB+ | 实际内存容量 |
保护机制 | 提供页级保护 | 无保护(由内核控制) |
内核通过页表(Page Table)将虚拟地址映射到物理地址。
四、Page 和 Page Table(页与页表)
-
默认页大小为 4KB(可通过
getconf PAGE_SIZE
查看) -
每个进程都拥有一个独立的页表
-
页表项(PTE)记录了该页在物理内存中的位置、权限、是否在 swap 中等信息
多级页表(x86 通常是 3 级)是为了节省内存而设计的结构,类似树形结构。
五、地址空间结构(用户态 & 内核态)
一个 Linux 进程的虚拟地址空间大致如下:
0x00000000
↓
[ Text Segment ] # 代码段
[ Data Segment ] # 全局变量、静态变量
[ Heap ] # 动态分配区(malloc)
↑
[ Shared Libraries ]
[ Stack ] # 函数调用栈(从高地址向下增长)
0xC0000000 (32位) / 高位地址
六、内存分配机制详解
Linux 使用多种分配器管理不同用途的内存:
Buddy System(伙伴系统)
-
用于管理大块物理页(主要是页分配)
-
分配时以 2 的幂次分割
-
合并碎片时效率较高
Slab / Slub 分配器
-
用于内核对象管理(例如
task_struct
,inode
等) -
采用对象池缓存,降低频繁分配释放开销
-
Slub
是现代 Linux 的默认分配器
七、内存回收与 Swap 策略
回收机制:
-
页缓存回收(Page Cache)
-
文件映射回收(mmap)
-
共享内存回收
-
低内存时触发 swap
Swap 分区:
-
当物理内存不足时,内核会将不活跃的页面写入 swap 分区(虚拟内存)
-
虽然避免了 OOM,但性能极差(因为是磁盘)
# 查看 swap 使用情况
free -h
swapon --show
八、如何查看 Linux 内存状态?
常用命令:
free -h # 总览
top / htop # 动态观察
vmstat 1 # 内存、I/O、swap
/proc/meminfo # 系统内存详细数据
cat /proc/[pid]/maps # 某进程虚拟内存布局
示例:
cat /proc/meminfo | grep Mem
输出:
MemTotal: 16323456 kB
MemFree: 9323456 kB
Buffers: 234560 kB
Cached: 1234567 kB
九、开发者如何与内存交互?
用户空间:
-
使用
malloc/new
动态申请 -
mmap()
手动映射大内存 -
brk/sbrk
(glibc 低层接口) -
valgrind
检测内存泄漏
内核空间:
-
kmalloc
,vmalloc
申请内核内存 -
get_free_pages
申请页 -
slab_create
创建缓存池
十、总结
项目 | 说明 |
---|---|
管理机制 | 虚拟内存、页表、缓存等 |
分配策略 | Buddy、Slab、mmap 等 |
地址隔离 | 用户/内核空间划分明确 |
关键优势 | 安全、可扩展、支持交换 |
开发关注点 | 避免泄漏、合理分配、理解堆栈布局 |