slab内存分配器是linux内核中比较经典的内存分配器,目前已经被slub内存分配器取代了。不过为了致敬经典,更是为理解slub分配器做铺垫,我还是会从slab分配器讲起。
为什么需要slab内存分配器?
这个问题其实很好回答,之所以提出slab分配器,是因为buddy system只能按page对齐来分配内存。然而大多数情况下,需要的内存size都不是按page对齐的,如果直接通过buddy system分配内存,就会出现很大的内存碎片,内存碎片即分配了却没有使用,也无法再被分配的内存。
正是由于buddy system的这种限制,slab分配器应运而生。slab分配器的底层依托于buddy system,上层却对用户提供了更加灵活的内存分配服务。
slab分配器工作机制主要包括两点:
- 从buddy system分配pages,放入slab分配器内存池,也可以称为cache。
- 用户调用slab分配器提供的内存分配接口如kmalloc,从slab分配器内存池中分配内存,内存的size没有按page size对齐的要求。
当然,以上两点只是slab分配器最本质的工作机制,我们后面会介绍细节。
slab分配器基础概念
什么是slab?
slab是slab内存分配器从buddy system申请页面的基本单位。然而slab的大小不是固定的,slab从属于某个kmem cache实例,不同的kmem cache实例,其slab的大小是不同的。slab的大小必须是2^order个pages,order不能超过buddy system所支持的最大的order。
slab内存分配器从buddy system分配了slab之后,会将其挂在对应的kmem cache实例的node节点。
什么是object?
object是slab内存分配器对外提供的申请内存的基本单位。slab内存分配器从buddy system申请了buddy之后,会将其拆分成一个个object,并缓存在kmem cache实例的cpu_cache中,用户申请内存时,其实获取的就是一个个object。
一旦object缓存耗尽,就会重新从buddy system申请slab,并将其拆分成object,放入内存池。
什么是cache?
slab内存分配器中的cache跟硬件cache无关,是一个纯软件的概念。slab内存分配器有两种cache,一个是slab的cache,一个是object的cache。slab内存分配器从buddy system获取页面后,会将其加入kmem cache的node节点,这个就是slab的cache;将slab拆分成多个object,并将object加入kmem cache的cpu_cache内存池,这个就是object的cache;可以看到这两种cache实际是对共同的物理页面的两种缓存形式。