Linux内核中采用了一种同时适用于32位和64位系统的内存分页模型,对于32位系统来讲,两级页表足够用了,而在x86_64系统中,用到了四级页表。四级页表分别为:linux
页全局目录包含若干页上级目录的地址,页上级目录又依次包含若干页中间目录的地址,而页中间目录又包含若干页表的地址,每个页表项指向一个页框。Linux中采用4KB大小的页框做为标准的内存分配单元。算法
在实际应用中,常常须要分配一组连续的页框,而频繁地申请和释放不一样大小的连续页框,必然致使在已分配页框的内存块中分散了许多小块的空闲页框。这样,即便这些页框是空闲的,其余须要分配连续页框的应用也很可贵到知足。数组
为了不出现这种状况,Linux内核中引入了伙伴系统算法(buddy system)。把全部的空闲页框分组为11个块链表,每一个块链表分别包含大小为1,2,4,8,16,32,64,128,256,512和1024个连续页框的页框块。最大能够申请1024个连续页框,对应4MB大小的连续内存。每一个页框块的第一个页框的物理地址是该块大小的整数倍。缓存
假设要申请一个256个页框的块,先从256个页框的链表中查找空闲块,若是没有,就去512个页框的链表中找,找到了则将页框块分为2个256个页框的块,一个分配给应用,另一个移到256个页框的链表中。若是512个页框的链表中仍没有空闲块,继续向1024个页框的链表查找,若是仍然没有,则返回错误。性能
页框块在释放时,会主动将两个连续的页框块合并为一个较大的页框块。操作系统
1)尽管伙伴内存算法在内存碎片问题上已经作的至关出色,可是该算法中,一个很小的块每每会阻碍一个大块的合并,一个系统中,对内存块的分配,大小是随机的,一片内存中仅一个小的内存块没有释放,旁边两个大的就不能合并。对象
2)算法中有必定的浪费现象,伙伴算法是按2的幂次方大小进行分配内存块,固然这样作是有缘由的,即为了不把大的内存块拆的太碎,更重要的是使分配和释放过程迅速。可是他也带来了不利的一面,若是所需内存大小不是2的幂次方,就会有部分页面浪费。有时还很严重。好比原来是1024个块,申请了16个块,再申请600个块就申请不到了,由于已经被分割了。blog
3)另外拆分和合并涉及到 较多的链表和位图操做,开销仍是比较大的。生命周期
Buddy(伙伴的定义):进程
这里给出伙伴的概念,知足如下三个条件的称为伙伴:
1)两个块大小相同;
2)两个块地址连续;
3)两个块必须是同一个大块中分离出来的;
假如系统须要4(22)个页面大小的内存块,该算法就到free_area[2]中查找,若是链表中有空闲块,就直接从中摘下并分配出去。若是没有,算法将顺着数组向上查找free_area[3],若是free_area[3]中有空闲块,则将其从链表中摘下,分红等大小的两部分,前四个页面做为一个块插入free_area[2],后4个页面分配出去,free_area[3]中也没有,就再向上查找,若是free_area[4]中有,就将这16(2222)个页面等分红两份,前一半挂如free_area[3]的链表头部,后一半的8个页等分红两等分,前一半挂free_area[2]的链表中,后一半分配出去。假如free_area[4]也没有,则重复上面的过程,知道到达free_area数组的最后,若是尚未则放弃分配。
内存的释放是分配的逆过程,也能够看做是伙伴的合并过程。当释放一个块时,先在其对应的链表中考查是否有伙伴存在,若是没有伙伴块,就直接把要释放的块挂入链表头;若是有,则从链表中摘下伙伴,合并成一个大块,而后继续考察合并后的块在更大一级链表中是否有伙伴存在,直到不能合并或者已经合并到了最大的块(222222222个页面)。
slab是Linux操做系统的一种内存分配机制。其工做是针对一些常常分配并释放的对象,如进程描述符等,这些对象的大小通常比较小,若是直接采用伙伴系统来进行分配和释放,不只会形成大量的内碎片,并且处理速度也太慢。而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其从新保存在该列表中,而不是直接返回给伙伴系统,从而避免这些内碎片。slab分配器并不丢弃已分配的对象,而是释放并把它们保存在内存中。当之后又要请求新的对象时,就能够从内存直接获取而不用重复初始化。
slab 分配器首先从部分空闲的slab 进行分配。如没有,则从空的slab 进行分配。如没有,则从物理连续页上分配新的slab,并把它赋给一个cache ,而后再重新slab 分配空间。
与传统的内存管理模式相比, slab 缓存分配器提供了不少优势。
一、内核一般依赖于对小对象的分配,它们会在系统生命周期内进行无数次分配。
二、slab 缓存分配器经过对相似大小的对象进行缓存而提供这种功能,从而避免了常见的碎片问题。
三、slab 分配器还支持通用对象的初始化,从而避免了为同一目的而对一个对象重复进行初始化。
四、slab 分配器还能够支持硬件缓存对齐和着色,这容许不一样缓存中的对象占用相同的缓存行,从而提升缓存的利用率并得到更好的性能。