内存管理篇-13slab、slob和slub分配器

内存管理篇-13slab、slob和slub分配器slab 机制是对伙伴系统的补充和改进 主要是因为伙伴系统的粒度最小是页 需要进一步细化粒度 因此引入了 slab 机制

---这里讲得还不是很细节。需要结合其他资源和源码分析。

1.实现机制和介绍

slab机制是对伙伴系统的补充和改进,主要是因为伙伴系统的粒度最小是页,需要进一步细化粒度,因此引入了slab机制。slab机制从伙伴系统统申请到页后,进行切割成大小相同的free object。图中特意举例了tash_struct inode_cache kmalloc-1k几个场景,是由于他们在内核中会频繁的申请和释放,因此内核需要一个这样的小的且不同的大小的内存释放申请机制。于是就有了slab slob slub分配器。

Slab 分配器是 Linux 内核中最经典的缓存管理机制之一,它通过预分配固定大小的对象来减少内存碎片,并提供高效的缓存管理。

  • 缓存管理: Slab 分配器维护了一个缓存层次结构,其中每个缓存都有一个特定的对象大小。
  • 对象预分配: 当需要分配对象时,Slab 分配器会预先分配一定数量的对象,并将它们存储在一个称为“slab”的结构中。
  • 对象释放: 当对象不再使用时,它们不会立即返回给操作系统,而是保留在缓存中,供后续请求重用。
  • 对象重用: Slab 分配器能够高效地重用已分配的对象,从而减少了内存分配和释放的开销。

Slob 分配器是 Slab 分配器的一个变种,它允许对象大小有一定的变化范围,而不是严格固定。

  • 动态大小: Slob 分配器支持动态大小的对象,它可以为不同大小的对象分配不同的 slab。
  • 内存池: Slob 分配器使用内存池来管理不同大小的对象,从而提高了灵活性。
  • 缓存管理: Slob 分配器也维护了一个缓存层次结构,用于管理不同大小的对象。

Slub 分配器是现代 Linux 内核中默认使用的缓存管理机制,它结合了 Slab 和 Slob 分配器的优点,并引入了一些新的特性。

  • 简化: Slub 分配器比 Slab 和 Slob 分配器更简单,减少了内存管理的复杂性。
  • 对象大小: 支持动态大小的对象。
  • 缓存管理: Slub 分配器维护了一个缓存层次结构,用于管理不同大小的对象。
  • 内存跟踪: Slub 分配器提供了更好的内存跟踪和调试能力。
  • NUMA 支持: Slub 分配器改进了 NUMA 环境下的内存分配性能。

2.核心结构体

slab的架构,主要就是通过三个结构体搭建起来的。kmem_cache, kmem_cache_cpu, kmem_cacahe_node.

  • kmem_cache主要管理具有相同大小内存块的slab,系统会申请多个kmem_cache进行管理不同大小的slab,每个kmem_cache之间连起来。

  • 成员1:struct kmem_cache_node *node[N], 结构体指针数组,每个node有一个素,指针指向了一个slab链表。这片内存放在哪里呢?是不是每个node上分配一片小的区域给slab分配器使用?
  • 成员2:struct kmem_cache_cpu __percpu *cpu_slab,__percpu宏表示每个cpu都有本地缓存,这里应该指的是从内存中拷贝多份内存,供多个CPU缓存起来。
  • slab实际上就是一个来自伙伴系统的内存块,freelist指针指向空闲的对象,
  • struct page *partial;指的时未分配使用的slab,需要保存起来。假如第一次从伙伴系统申请了4K的内存,构造了32B大小的slab2,用户用无法申请后,此时用户再从partial申请,用freelist指针指向它。??
  • slab申请内存的时候,先从本地cpu的缓存slab申请,如果本地的申请完了,就会从node节点上申请。如果两个地方的都用完了,就会再去伙伴系统重新申请。

3.实践

#include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> //假如我们内核中需要频繁的创建和释放这个student结构体,因此我们就需要slab缓存提高它的性能 struct student { int id; int age; float score; void (*print_score)(int id); void (*print_age)(int id); }; struct kmem_cache *stu_cache; struct student *p; void stu_ctor(void *p) { ;// 回调函数,在create的时候会调用它,内核一般是这样初始化init object here } static int __init hello_init(void) { //创建slab的时候,会指定回调函数,创建对象的时候就会回调,失败会发送panic信息 stu_cache = kmem_cache_create("student", sizeof(struct student), 0, SLAB_PANIC|SLAB_ACCOUNT,stu_ctor); BUG_ON(stu_cache == NULL); printk("stu_cache = %x\n", (unsigned int)&stu_cache); p = kmem_cache_alloc(stu_cache, GFP_KERNEL); if(p) { printk("p object size = %x\n", sizeof(*p)); printk("p object size = %d\n", sizeof(struct student)); } return 0; } static void __exit hello_exit(void) { kmem_cache_free(stu_cache, p); kmem_cache_destory(stu_cache); }

 问题:这里struct student是20字节,但是slabino显示的objsize是24字节,为什么?因为freelist二级指针,它会多一个指针的空间指向下一个内存区域

今天的文章 内存管理篇-13slab、slob和slub分配器分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2024-12-21 18:27
下一篇 2024-12-21 18:21

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/92380.html