页框管理
- Linux采用4KB页框大小作为标准内存分配单元
页描述符
- 描述页框的信息
- 页描述符字段
- _count: 页的引用计数器,该字段为-1标示页框空闲
- flags: 描述页框状态的标志
非一致内存访问(NUMA)
- 不同CPU访问页面所需的时间不一样
- 对于每个CPU,内核试图把耗时节点的访问次数捡到最少
内存管理区
80x86硬件的约束
- DMA 只能对RAM的前16MB进行寻址
- 线性地址空间太小,CPU不能直接访问所有的物理内存
3个内存管理区
- ZONE_DMA: 包含低于16MB的内存页框
- ZONE_NORMAL: 包含16MB且低于896MB的内存页框
- ZONE_HIGHMEM: 高于896MB的页框
保留的页框池
- 减少内存分配失败情况的发生
- 保留内存
分区页框分配器
- 处理对连续页框组的内存分配请求
- 处理对连续页框组的内存分配请求
高端内存页框的内核映射
- 永久内核映射
- 可能阻塞当前进程,不能用于中断处理程序和可延迟函数
- 临时内核映射
- 不是阻塞当前进程
- 只有很少的临时内核映射可以同时建立
- 非连续内存分配
- 永久内核映射
伙伴系统算法
- 解决外碎片问题:尽管有足够的空闲页框满足要求,但是无法满足分配一块大的连续页框
本质上避免外碎片的方法
- 利用分页单元把一组非连续的空闲页框映射到连续的线性地址空间
- 记录现有的页框分块情况,避免为满足小块的请求而分割打的空闲块
伙伴算法
- 所有空闲页框分组,为11个块链表
- 每个链表分表包含大小为1,2,4,8,16,32,64,128,256,512和1024个连续的页框
- 数据结构
- 分配块:__rmqueue函数实现(P314)
- 释放块:__free_pages_bulk函数实现(P315)
每个CPU页框高速缓存
- 包含一些预分配的页框,满足本地CPU发出的单一内存请求
内存区管理
高速缓存描述符和slab描述符
普通和专用高速缓存
- 普通高速缓存:只由slab分配器用于自己的目的
- 专用高速缓存:由内核其余部分使用
对象描述符
slab对象的分配和释放(P337)
内存池
- 动态内存的储备,只能被特定的内核成分使用
非连续内存区管理
- 完全避免外碎片,但需要打乱内核页表
- 非连续内存区的描述符
- 非连续内存区的分配和释放(P345)