buddy 与 slab 对比
算法 | 特点 | 使用者举例 |
---|---|---|
buddy | 基于页 | alloc_page() |
slab | 基于具体的数据对象,缓存池 | kmalloc() |
buddy
slab
感觉slab就是缓存池的思想,类似Threadx的字节池和块池。假如想要在Threadx中实现一个slab,就可以利用块池。可以利用sipc的smem来实验验证一下
缓存分配器背后的想法
- 将内存划分为对象池,每个对象池包含同样大小的对象,并且不同的池包含不同的大小。因此,当有人请求一个给定大小的内存块,找到第一个能够足够大的块的内存池,分配给他完事。这就是所有要做的事情。
- 需要考虑一些事情:每个池多大为好?如果我们用完一个池的对象,我们如何创建更多的池?我们如何追踪池子的对象是free的或者在使用中?我们应该有多少池?池大小之间的gap多大为好?
kmalloc()是如何工作的
内存被分为包含对象的池。每个池被认为是一个缓存,内核中有许多这样的缓存池。这些池的关键数据结构是:kmem_cache_t。它用来处理池用到的所有信息,比如每个对象的大小以及每个池中对象数目。驱动能够通过kmem_cache_create函数创建它选定大小的内存池。这个函数创建调用者给定大小的内存,然后将它插入已创建的全局内存池cache_cache。cache_cache是一个静态kem_cache_t对象,用来管理所有系统级缓存。你可以通过/proc/slabinfo看到所有缓存大小。除了全局缓存池,我们也有通用缓存池。通用缓存池是一个缓存数组,每个元素后一个是前一个的2指数幂倍。在IA-32中以32开始,一直到131072*2.对于每个大小,有两个cache,一个为普通内存,一个为DMA。在IA-32,DMA内存必须是16位可寻址的。这就是kmalloc如何工作的。当kmalloc被调用,他搜索通用缓存知道找到一个合适的缓存块。然后调用__kem_cache_alloc来从缓存获取对象并返回给调用者。同样的,kfree只是通过调用__kem_cache_free来返回对象到他的缓存池。