一、Linux内存结构分为:node(节点),zone(区域),page(页框描述符)
node ----{ zone-----{ page
……
{ zone-----{page
二、映射高端内存的方法:
永久映射(permanent kernel mapping)和暂时映射(temporary kernel mapping),以及不连续内存申请(noncontiguous memory )
1)永久映射:
使用内核中专门保存的一个页表来实现,相当于是建立页表映射,因为涉及到操作页表有可能休眠
void *kmap(struct page * page);
用法:
struct page * page = alloc_pages(GFP_HIGHMEM,1);
int * vaddr = kmap(page);
2)临时映射:
使用内核中专门保存的一个页表项(page table entry)来实现,相当于是建立页表映射,不会导致休眠
void *kmap_atomic(struct page * page);
用法:
struct page * page = alloc_pages(GFP_HIGHMEM,1);
int * vaddr = kmap_atomic(page);
三、内存区域管理
zone和buddy算法解决了申请页框时的问题:硬件限制和内存碎片。
而在实际的内核编程中最常碰到的是各种不同size数据结构mem request的申请和释放,要解决这种类型内存请求的效率和内存碎片问题,
就需要用到cache和slab,原因有:
1)相同size内存的申请和释放相当常见,为了避免内核疲于应付这些工作,内核提供了一个方法:基于cache来建立slab系统,每个slab
对应相应的内存单元size,申请到来时及时满足,释放时进行软件回收,这样就避免了频繁做页框动作。
2)为了解决内存碎片问题,
四、非连续内存区的管理
非连续内存区是指线性地址连续,物理地址不连续的vmalloc区域,该区域用于映射超过896MB的物理内存页框,
通常只适用于X86架构,ARM等嵌入式架构很少会用到这么大的内存量,因此在ARM架构下kmap,永久内核映射,
固定内核映射都用不到。
其实vmalloc的实现方法就是通过alloc_pages来申请数个页框,当然这些页框位于HIGHMEM,来满足申请的内存大小,
然后修改页表,建立VMALLOC段线性地址到这些页表的映射。