SLAB,SLUB,SLOB

Linux内核:slab/slob/slub

  • Slab是基础,是最早从Sun OS那引进的;
  • Slub是在Slab上进行的改进,在大型机上表现出色(不知道在普通PC上如何),据说还被IA-64作为默认;
  • Slob是针对小型系统设计的(废弃)

SLAB分配器

作为基础,当然要学习。
我们知道,BUDDY算法是基于页的分配管理,在内存中大部分使用却是以字节进行分配的,slab就是解决小内存分配的

推荐:Linux slab 分配器剖析

重点关注:

  • SLAB是如何分配和释放小内存块的?
  • 缓存着色啥意思?

用户使用

  1. #include <linux/slab.h>
  2. /** 创建和释放slab描述符
  3. * kmem_cache_create - Create a cache.
  4. * @name: /proc/slabinfo . procfs下可见
  5. * @size: 缓存对象大小
  6. * @align: 缓存对象需要对齐的字节数
  7. * @flags: SLAB flags
  8. * @ctor: A constructor for the objects. 对象构造函数,直接为NULL即可。
  9. * Return: a pointer to the cache on success, NULL on failure.
  10. */
  11. struct kmem_cache *
  12. kmem_cache_create(const char *name, unsigned int size, unsigned int align,
  13. slab_flags_t flags, void (*ctor)(void *));
  14. void kmem_cache_destroy(struct kmem_cache *s);
  15. /** 分配和释放缓存对象
  16. * kmem_cache_alloc - Allocate an object
  17. * @cachep: The cache to allocate from.
  18. * @flags: See kmalloc().
  19. *
  20. * Allocate an object from this cache. The flags are only relevant
  21. * if the cache has no available objects.
  22. *
  23. * Return: pointer to the new object or %NULL in case of error
  24. */
  25. void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags);
  26. void kmem_cache_free(struct kmem_cache *cachep, void *objp);

如果单纯使用,那么以上接口足够。 但内部实现仍然懵逼

slab描述符

slab分配器

  1. // linux-5.7.14/include/linux/slab_def.h
  2. #include <linux/slab_def.h>
  3. /*
  4. * struct array_cache
  5. *
  6. * Purpose:
  7. * - LIFO ordering, to hand out cache-warm objects from _alloc
  8. * - reduce the number of linked list operations
  9. * - reduce spinlock operations
  10. *
  11. * The limit is stored in the per-cpu structure to reduce the data cache
  12. * footprint.
  13. *
  14. */
  15. struct array_cache {
  16. unsigned int avail;
  17. unsigned int limit;
  18. unsigned int batchcount;
  19. unsigned int touched;
  20. void *entry[];
  21. };
  22. struct kmem_cache {
  23. struct array_cache __percpu *cpu_cache; // percpu 本地CPU对象缓冲池

描述符分配流程

细节分配参考: SLUB分配算法

  1. kmem_cache_create
  2. kmem_cache_create_usercopy
  3. get_online_cpus() + get_online_mems() // cpu和mem加锁
  4. kmem_cache_sanity_check
  5. __kmem_cache_alias(name, size, align, flags, ctor);
  6. create_cache(cache_name, size,
  7. calculate_alignment(flags, align, size),
  8. flags, useroffset, usersize, ctor, NULL, NULL);
  9. put_online_mems() + put_online_cpus() // cpu和mem释放锁

__kmem_cache_alias
该函数检查已创建的slab是否存在与当前想要创建的slab的对象大小相匹配的,如果有则通过别名合并到一个缓存中进行访问

  1. __kmem_cache_alias(name, size, align, flags, ctor);
  2. find_mergeable(size, align, flags, name, ctor); // 查找可合并slab的kmem_cache结构

SLUB分配器

https://blog.csdn.net/juS3Ve/article/details/79124544?utm_source=blogxgwz2
看了下ubuntu18.04 /boot/config-5.4.0-52-generic下的配置,也是用SLUB,这里也学习下这个玩意。