【Linux内核】内存管理——Buddy、Slab分配器

转载请注明出处: https://www.cnblogs.com/Ethan-Code/p/16651217.html

Buddy分配器

前面提到,Linux用内存分页的形式将物理内存组织起来,相比分段的优点就是分页的颗粒度更小,可以减少外部内存碎片,但是却不能完全消除内存碎片。

内存分页机制把4K为单位的物理内存页框组织起来,使其在虚拟内存上连续。但是当需要申请连续物理内存页框的时候,随着进程的对内存的申请和释放,系统的内存会不断的区域碎片化,分页机制就不一定能保证有足够的连续物理内存页了。

因此需要有引入一种机制来管理物理内存页,Linux使用buddy分配器来组织物理内存页框,对物理内存页进行合理的分配和回收,让内存分配与相邻内存合并能快速进行,用于缓解内存碎片化

buddy system 以页为单位,把内存分成 11 个组,对应11种不同大小的连续内存块,每组中的内存块大小都相等,为2的幂次个物理页。

系统中存在 2^0 ~ 2^10 这11种大小不同的内存块,对应内存块大小为4KB ~ 4M。内核用11个链表来管理11种大小不同的内存块。

一共有11个链表,最大order为10,那么最大可分配的内存就是4M。

buddy内存块

一个连续的物理内存块平均拆分成两个大小是原来一半的块单元,这样的两个块互为buddy。两个块的大小必须一样大并且内存地址相邻(才可以合并)。

另一个伙伴性质是所有块单元在内存中的地址必须能被它自己的大小整除。

内存分配

当分配内存时,会把所需内存向上取整为2的倍数。

优先从对应大小的内存块链表上查找空闲内存块。

若没有空闲内存块,则会从更大一级的内存块链表查找,找到空闲内存块后,将大的内存块分成相同大小的2部分。

一部分插入对应的小一级的内存块链表,另一部分分配给用户使用。

如果大一级的内存块链表中没有空闲内存块,则会向更大的内存块链表中查找,然后一层层二分下来,分到合适大小后分配给用户,其他的都插入对应的内存块链表中。

内存回收

当回收一个内存块,会将该内存块插入到对应的链表中,然后查询其buddy内存块是否也在链表上,如果是则合并两个内存块,然后插入到大一级的内存块链表中。重复该逻辑。

Slab分配器

slab 是 Linux 操作系统的一种内存分配机制。其工作是针对一些经常分配并释放的对象,如进程描述符等,这些对象的大小一般比较小,如果直接采用伙伴系统来进行分配和释放,不仅会造成大量的内存碎片,而且处理速度也太慢。而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给buddy system,从而避免产生内部碎片。

slab分配器并不丢弃已分配的对象,而是释放并把它们保存在内存中。当以后又要请求新的对象时,就可以从slab直接获取而不用重复初始化。

slab也是从buddy system中分配的一个或多个连续内存页,主要用来解决buddy system 带来的内部内存碎片,将经常申请的内核内存结构视为对象,缓冲在slab的cache中,申请的时候可以快速分配,释放的时候回收回cache。这样可以降低buddy system中这些小内存申请带来的分配内存页的时间开销和空间开销。

重要接口函数:

/*分配一块给某个数据结构使用的缓存描述符
  name:对象的名字   size:对象的实际大小  align:对齐要求,通常填0,创建是自动选择。   flags:可选标志位    ctor: 构造函数 */
struct kmem_cache *kmem_cache_create( const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void*));
/*销毁kmem_cache_create分配的kmem_cache*/
int kmem_cache_destroy( struct kmem_cache *cachep);

/*从kmem_cache中分配一个object  flags参数:GFP_KERNEL为常用的可睡眠的,GFP_ATOMIC从不睡眠 GFP_NOFS等等等*/
void* kmem_cache_alloc(struct kmem_cache* cachep, gfp_t flags);
/*释放object,把它返还给原先的slab*/
void kmem_cache_free(struct kmem_cache* cachep,  void* objp);

有点难,暂时不想花时间学太深,挖个坑,以后有兴趣再回头补。

好文推荐:https://www.cnblogs.com/encode/p/4967259.html
https://blog.csdn.net/rikeyone/article/details/85054231

猜你喜欢

转载自blog.csdn.net/weixin_45636061/article/details/127184863