一:伙伴系统算法(解决外碎片问题)
1:原理
Linux伙伴算法把所有空闲页面分为10个块组,每组中的块的大小是2的幂次方个页面。比如,第0组中的块都为2的0次幂(1个页面),第一组块的大小都是2的一次幂(2个页面),第9组中块的大小是2的9次幂(512个页面),每一组中,块是大小相同的,并且形成一个链表。
简单说明算法工作原理
分配:假设要求分配的块的大小是128个页面(由多个页面组成的块叫做页面块),该算法先在块大小为128个页面的链表中查找,看是否有这样的空闲块,如果有,就直接分配;如果没有,该算法会查找下一个更大的块,具体的说,就是在块大小256个页面的链表中查找一个空闲快。如果存在这样的空闲快,内核就把这个256个页面分为2等份,一份分配出去,另一份插入到块大小为128个页面的链表中,如果在块大小为256个页面的链表中也没有找到空闲块面,就继续找更大的块,即512个页面块,如果存在这样的块,内核就把512个页面的块中分出128个页面满足要求,然后在384个页面去除256个页面插入到块大小位256个页面的链表中,然后把剩下128个页面插入到块为128个页面的链表中。
如果512个页面的链表中还没有空闲块,该算法就放弃分配,并发出出错信号。
释放:上边 相反的过程
满足连个条件的块称为伙伴:两个快的大小相同;两个快的物理地址连续;
2:数据结构分析
管理区数据结构 struct zone_struct 中,涉及到空闲区数据结构:
free_area_t free_area[MAX_ORDER];
#define MAX_ORDER 10 //伙伴算法10个块组,对应10个数组元素
typedef struct free_area_struct
{
struct list_head free_list; //通用的双向链表,链表中元素类型为mem_map_t(即struct page 结构)
unsigned int *map;//指向一个位图,其大小取决于现在的页面数
} free_area_t;
图片举例:
二:物理页面的分配和释放
当一个进程请求分配连续的物理页面时,可以通过调用alloc_pages()来完成,此函数两个版本,一个在mm/numa.c,另一个在mm/page_alloc.c。编译时根据所定义的条件选项CONFIG_DISCONTIGMEM进行决定。
1:非一致存储结构(NUMA)中页面分配
释放:_free_pages()
三:slab 分配基机制
实质:一种针对小内存区的内存分配机制,特点是基于对象进程管理,slab分配算法采用cache存储内核对象。slab缓存,从缓存中分配和释放对象然后销毁缓存的过程必须要定义一个kmem_cache对象,然后对其进行初始化这个特定的缓存包含32个字节。
高速缓存的内存区域划分很多个slab,每个slab由一个或多个连续的页框组成,这些页框中包换已经分配的对象,也包含空闲对象。
1:slab数据结构
slab分配模式有两个主要的数据结构,一个缓冲区的结构kmem_cache_t,另一个slab结构kmem_slab_t
2.缓冲区
每个缓冲区管理一个slab链表,slab按序分为3组,第一组全满的slab(没有空闲的对象),第二组slab只有部分对象被分配,部分对象还空闲,第三组slab中的对象全部空闲。
这样分组,是为了对slab有效管理,每个缓冲区还有一个轮转锁(spinLock),在对链表进行修改时候,用轮转锁进行同步。