昨天讲过了远古时代的记忆体管理,跟後续为了解决最古老的记忆体管理所引发的问题而接着有的分段管理与分页管理,今天要提到的是Linux 中使用到的动态记忆体管理的三个机制,分别是 buddy, slab, slob。
这个算法正如其名,是让记忆体分配的时候一对一对的,这个作法会将记忆体页面的大小以幂次分组,从 $2^0$ ~ $2^{11}$,将所有未使用的页面分组成11个空闲记忆体区块的列表,链表里面依序的空闲记忆体大小分别是 1, 2, 4, 8, 16...... 1024个连续的页面,因为每页的大小是4KB,所以最大的连续大小就是4MB,更为了管理方便,会依照记忆体的性质再分为三个不同的链表,分别是不可移动、可回收、可移动三种,因为世界上所有的数字都可以由二的幂次组成,所以这个演算法便有所依据。
以下举出一个例子
在内部保存一些 2 的 N 次方空间记忆体片段,如果要分配 3 pages,去 4 pages 的列表里面取一个,分配 3 个之後将剩下的 1 个放回去,记忆体释放的过程刚好是一个反向过程。
在 <mm/page_alloc.c> 里面可以看到跟Buddy 系统有关系的一些函数。
在 get_page_from_freelist()
就是从Buddy系统的link list中尝试分配里的页面; free_page()
则是释放实体记忆体,其中有个函数是 __free_one_page()
,负责检查是否有检查是否有page 需要合并, 在里头会呼叫 page_is_buddy()
函数检查要释放的记忆体区块A 邻近的记忆体区块是否是未使用的,如果未使用才会继续进行合并。
对於某两个记忆体区块是否能够合并需要判断以下三个条件
buddy system 分配记忆体时,是以页面为单位,但是在实际系统的应用上,有许多的记忆体需求只有需要字节等级的,此时如果仍用页面分配,会造成非常大的记忆体空间浪费,为了解决这个问题slab allocator就出现了。
Slab 做的事情是在 buddy system之後,利用那些连续的物理页面实现了自己的机制。
以下列出几个与slab相关的函数
//创造一个slab 的descriptor
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, unsigned long floags, void (*ctor)(void *))
//释放 slab descriptor
void kmem_cache_destroy(struct kmem_cache *s)
//分配记忆体对象
void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags);
//释放记忆体对象
void kmem_cache_free(struct kmem_cache *, void *);
slub 是slab的改良版,在多数情况下Slab可以正确地完成任务,但是在这个大规模多处理器系统和NUMA系统的广泛应用下slab逐渐透露出不足。
第二十六天 各位点进来的朋友,你们好阿 小的不才只能做这个系列的文章,但还是希望分享给点进来的朋友,...
问题及解决方法 资料集问题: 图档没有文字却有标签。 一张图片多个文字。 标签错误。 图档的字不明确...
Q: 还是Loading吗? A: 一大系列!接下来的样式会比较不同~ 上两篇做完圆圈的Loadi...
Linux 的 Distro 很多,今天笔记一下在 openSUSE 上启用呒虾米的纪录。 从系统设...
本文目标 认识 PLIC, IRQ 与 ISR 综合先前所学,应用在实际案例上 进入正题 PIC P...