Linux内存管理
Linux负责把有限的物理内存(RAM)抽象成大量连续的虚拟地址空间,并通过页表、分页、缓存、回收和交换机制,在进程之间安全、高效地分配和复用内存。
1.内存管理逻辑图
1 | 进程 |
2.虚拟内存
假设机器有:
1 | 物理内存:16GB |
一个进程看到的却不是简单的16GB物理内存,而是一个虚拟地址空间。
CPU访问这个地址时,大致经过:
1 | 虚拟地址 |
3.内存以Page为基本单位
Linux不会通常以“1字节”为单位管理物理内存。最基本的单位是:Page(页)
在常见x86-64系统中:
1 | 1 Page = 4096 bytes |
物理内存可以想象成:
1 | RAM |
Linux内核使用struct page等数据结构管理这些物理页。因此Linux实际上是在管理大量的物理页框(Page Frame)。
4.整个内存申请流程串起来
假设:
1 | char *p = malloc(100 * 1024 * 1024); |
可以发生这样的事情:
1 | malloc() |
如果以后内存压力变大:
1 | RAM压力 |
如果最终还是不够:
1 | OOM |
5.从Linux源码角度看
| 模块 | 主要负责 |
|---|---|
| Page Table | 虚拟地址→物理地址 |
| MMU/TLB | 地址转换和缓存 |
| Page Fault | 缺页处理 |
| Buddy Allocator | 物理页分配 |
| SLUB | 内核对象分配 |
kmalloc |
内核小块内存 |
vmalloc |
虚拟连续、物理不连续内存 |
mmap |
建立用户空间映射 |
brk |
调整进程heap |
| Page Cache | 文件数据缓存 |
| Reclaim | 内存回收 |
| LRU | 页面活跃度管理 |
| Swap | 将部分匿名内存换出 |
| OOM | 内存耗尽处理 |
| cgroup | 对进程组进行内存资源限制 |
| NUMA | 多节点内存管理 |
最关键的主线其实只有:
虚拟地址→页表→物理Page→Page Fault→内存分配→回收→Swap/OOM。