内存分配机制
# 概述
Linux支持多种内存分配机制。分配物理内存页框的主要机制是页面分配器,它使用了著名的伙伴算法。
# buddy伙伴算法
在Linux中内存分配的基本单位是page frame页,对应的分配器主要是buddy伙伴分配器和slab。在说这两个分配器之前,可以先说下最原始的分配模型:空闲链表和内存池。
- 空闲链表:就是将内存中的所有空闲内存块用链表的形式链起来free list。在进行内存分配时,扫描free list分配一个空闲的块给当前进程。但是这样是很容易产生外部碎片的。
- 内存池:将一块大内存分成很多小内存,不同的内存又按照不同的尺寸分成大小相同的块。同一内存池中的空闲内存块按照free list链接起来。
buddy伙伴分配器就是基于内存池的思想建立起来,他是在内存释放的时候,会先去检查物理上相邻的左右page frame,如果相邻的page frame也是空闲的就会合成一个更大的空闲内存。
每个内存域都关联了一个staruct zone实例,其中保存了用于管理伙伴数据的主要数组。
# slab分配器
buddy内存分配的单位是page frame的,他的大小是4KB。对于小于4KB的小内存分配来说也用buddy的话会产生很多内部碎片,内存分配使用的效率不高。这就诞生了slab分配器的原因。slab分配器是基于对象进行管理的,相同类型的对象归位一类,每当要分配该类型对象的时候直接分配,这样避免了内部碎片。
slab分配过程,每次分配的时候直接从本地cpu告诉缓存中进行交互,这里是软件的高速缓存(kmem_cache中的array_cache),在cpu高速缓存中没有空闲对象的时候,就会从kmem_list中的slabs_partial链表中找一个空闲slab进行分配对象,partial中没有的时候再去slabs_free链表中找,slabs_free中没有的时候slab分配器通过buddy分配器申请page frame去形成一个新的slab进而来分配内存。**这里可以看到slab分配器是基于buddy分配器之上的一个抽象。**每个类型的对象都有自己的kmem_cache,这样会有很多的cache管理结构。
# 参考
[[虚拟内存管理#^z2mpge]]