Linux 内核内存管理详解
Linux 内核的内存管理是一个复杂而精妙的系统,负责管理物理内存和虚拟内存,为进程提供内存分配服务。以下是 Linux 内存管理的主要组成部分和工作原理的详细解析。
1. 内存管理架构概述
Linux 内存管理系统采用分层设计,主要包含以下几个层次:
-
硬件抽象层:处理特定架构的内存管理单元(MMU)细节
-
物理内存管理:处理物理页帧的分配和释放
-
虚拟内存管理:提供进程地址空间抽象
-
内存分配器:提供kmalloc、vmalloc等接口
-
用户空间接口:通过brk、mmap等系统调用提供服务
2. 物理内存管理
2.1 物理内存组织
Linux 使用节点(Node)、区域(Zone)、页(Page)的三级结构管理物理内存:
-
节点(Node):对应 NUMA 系统中的节点,每个节点有自己的内存
-
区域(Zone):每个节点分为多个区域,常见的有:
-
ZONE_DMA:用于DMA操作的内存
-
ZONE_NORMAL:普通映射的内存
-
ZONE_HIGHMEM:高端内存(32位系统)
-
-
页(Page):物理内存被划分为页帧(page frame),通常是4KB大小
2.2 伙伴系统(Buddy System)
Linux 使用伙伴系统管理物理页帧的分配和释放:
-
将空闲页帧组织成11个链表(0-10),每个链表包含2^n大小的页块
-
分配时从合适大小的链表获取,如果没有则分裂更大的块
-
释放时会尝试合并"伙伴"块(地址相邻且大小相同的空闲块)
// 内核中的伙伴系统主要接口 struct page *alloc_pages(gfp_t gfp_mask, unsigned int order); void free_pages(unsigned long addr, unsigned int order);
2.3 每CPU页框缓存
为减少伙伴系统的锁竞争,内核为每个CPU维护了:
-
热缓存:页表可能存在于CPU缓存中
-
冷缓存:页表不在CPU缓存中
3. 虚拟内存管理
3.1 地址空间布局
Linux 进程的虚拟地址空间通常布局如下:
0x00000000-0x08048000: 保留区域 0x08048000-0x...: 代码段(text) 0x...-0x...: 数据段(data) 0x...-0x...: 堆(heap,通过brk增长) 0x...-0x...: 共享库映射 0x...-0x...: 栈(stack,向下增长) 0xC0000000-0xFFFFFFFF: 内核空间(3GB/1GB分界)
3.2 页表管理
Linux 使用多级页表将虚拟地址转换为物理地址:
-
x86_32: 两级页表(PGD, PTE)
-
x86_64: 四级页表(PGD, PUD, PMD, PTE)
-
ARM: 三级页表
转换过程由 MMU 硬件完成,内核负责维护页表内容。
3.3 内存映射
Linux 通过 mm_struct 结构管理进程地址空间,vm_area_struct 描述虚拟内存区域(VMA):
struct mm_struct {
struct vm_area_struct *mmap; // VMA链表
pgd_t *pgd; // 页全局目录
// ...
};
struct vm_area_struct {
unsigned long vm_start; // 起始地址
unsigned long vm_end; // 结束地址
vm_flags_t vm_flags; // 权限标志
struct file *vm_file; // 映射的文件(如果有)
// ...
};
4. 内核内存分配器
4.1 SLAB分配器
用于内核对象的高效分配,特点:
-
缓存常用对象类型(如task_struct)
-
避免频繁初始化和释放的开销
-
减少内存碎片
主要接口:
kmem_cache_t *kmem_cache_create(...); void *kmem_cache_alloc(kmem_cache_t *, gfp_t flags); void kmem_cache_free(kmem_cache_t *, void *);
4.2 kmalloc/vmalloc
-
kmalloc:分配连续的物理内存,适用于小内存分配
void *kmalloc(size_t size, gfp_t flags);
-
vmalloc:分配连续的虚拟内存,物理内存可以不连续
void *vmalloc(unsigned long size);
5. 内存回收机制
5.1 页面缓存(Page Cache)
Linux 使用空闲内存作为文件缓存,通过以下机制回收:
-
LRU列表:维护活跃和非活跃页面
-
页面回收:当内存不足时回收非活跃页面
5.2 交换(Swap)
将不常用的内存页换出到磁盘交换分区:
-
使用交换缓存避免重复IO
-
交换优先级:匿名页 > 非活跃文件页
5.3 OOM Killer
当系统内存严重不足时,选择并终止占用内存多的进程。
6. 内存管理相关系统调用
-
brk/sbrk:调整堆的大小 -
mmap/munmap:内存映射/取消映射 -
mlock/munlock:锁定/解锁内存 -
madvise:提供内存使用建议 -
shmget/shmat:共享内存操作
7. 高级特性
7.1 透明大页(THP)
自动将小页合并为大页(2MB或1GB),减少TLB缺失。
7.2 内存压缩(zswap/zram)
在内存不足时压缩页面而非交换到磁盘。
7.3 控制组(cgroups)内存控制
限制和控制进程组的内存使用。
8. 性能调优参数
-
/proc/sys/vm/swappiness:控制交换倾向(0-100) -
/proc/sys/vm/dirty_ratio:控制脏页比例 -
/proc/sys/vm/overcommit_memory:内存过量使用策略 -
/proc/sys/vm/zone_reclaim_mode:NUMA内存回收模式
总结
Linux 内存管理系统通过精妙的分层设计和多种算法,实现了高效的内存管理。理解其工作原理对于系统调优、性能分析和内核开发都至关重要。随着硬件发展和新需求出现,Linux 内存管理仍在不断演进,如近年来对非易失性内存的支持等新特性。
1245

被折叠的 条评论
为什么被折叠?



