对于SLUB不熟的同学可以先跳过了,涉及的东西比较细致。
简单来说SLUB的结构是N(CPU数)个kmem_cache_cpu,和一个kmem_cache_node组成。其中kmem_cache_cpu的目的是为了从技术层面上提高CPU命中缓存,以及在同一个页面上不出现一个脏的内存(即不同时被多个CPU持有)。我把这个实现机制手工在WINDOWS下实现了一套,在开启多个kmem_cache_cpu的时候出现了个问题:
1.在释放对象的时候,判断是否是当前kmem_cache_cpu页面所在
2.如果是,则直接插入
3.如果不是,释放到邻居节点
如果是单个kmem_cache_cpu肯定没问题,但是在多个kmem_cache_cpu下,很可能会把其中一个kmem_cache_cpu已经持有的页面释放到邻居节点。举个例子:
假设一个页面地址是0-9,
kmem_cache_cpu1,持有A页面,空闲的情况为A0-A5
kmem_cache_cpu2,持有B页面,
当轮到kmem_cache_cpu2执行的时候,一个A页面的地址A6释放,程序检测到非B页面,则直接释放到邻居节点。那么这个时候A页面已经被切割成两段,并且在公共的邻居节点中。这个时候反而是增加了内存的脏度。后仔细看代码发现,源码中有这段:
struct kmem_cache_cpu {
void **freelist; /* Pointer to first free per cpu object */
struct page *page; /* The slab from which we are allocating */
int node; /* The node of the page (or -1 for debug) */
unsigned int offset; /* Freepointer offset (in word units) */
unsigned int objsize; /* Size of an object (from kmem_cache) */
#ifdef CONFIG_SLUB_STATS
unsigned stat[NR_SLUB_STAT_ITEMS];
#endif
};
注意到struct page *page;了吗?之前一直忽略它。并且真相在分配的函数里面,
如果freelist无效的话,会多查询一次page页的地址。
2011年1月15日增
细致看了下,觉得这个地方还是有BUG。
释放上就两个步骤
1)走本地PAGE
2)NODE节点
申请上比较复杂
1)走本地freelist
2)走本页page
3)走邻居节点
4)走系统
并且做了一些看似应该释放做的事:
1)如果page和freelist都为空,则走deactivate_slab();
deactivate_slab中有很多兼容的判断,要一一舍弃。阅读源码最痛苦的就是这点。
其中用到了个值page->inuse。这个值很奇怪,它指的是在kmem_cache_cpu当前+使用中的对象,如果释放了则
进行减一,所以你看不到他的++。
1)如果page->inuse大于0,并且freelist还有值,加入邻居。这个估计是兼容的代码,之前的判断freelist不为空
2)反之,加到邻居链表。
3)如果当前邻居链表满,则释放掉
2)如果freelist为空,page不为空,很可能其他的kmem_cache_cpu释放了对象,则走load_freelist:
疑问一:就是加入邻居链表和释放加入邻居链表的冲突。从条件上看,其实两个都是依赖page->freelist是否为空加入,但是在deactivate_slab加入邻居节点后,并没有对page->freelist进行处理,如果这时候有对象释放,是否会造成重复加入?
这个疑问是我弄错了,如果page->inuse==0,表示对象都已经释放,不会触发再次释放
疑问二:在多个kmem_cache_cpu情况下,释放的元素都是放到共同的邻居页面,很有可能被其他的kmem_cache_cpu直接取到,这样就造成2个不同的kmem_cache_cpu共享同个页面,这就违背了里面缓存命中的功能。
分享到:
相关推荐
Linux内核提供了几种不同的对象分配器,包括Slab、Slob 和 Slub 分配器。 #### Slub 分配器概述 Slub 分配器是Linux内核中的一种对象分配器,它是默认的分配器,并且适用于大型系统。与传统的Slab分配器相比,Slub...
仿照linux的buddy+slub内存管理算法,可以在裸机中应用标准内存管理库函数,如malloc free等
其中,slab、slob和slub是Linux内核中三种主要的内存分配器,它们在性能、效率和内存使用上各有特点。 首先,SLAB是一种非常古老的内存分配器,它最早由Sun公司的开发者提出并用在Solaris操作系统中。SLAB分配器的...
为了解决这个问题,Linux引入了SLAB、SLUB和SLOB分配器,它们能够在同一页面内独立分配小块内存,从而减少了内部碎片,提高了内存利用率。 Linux内存管理层次关系图进一步揭示了内存管理的复杂性。伙伴系统是基础,...
SLAB、SLUB和SLOB都是缓存分配器,它们维护了一个内存池,其中包含预分配且已初始化的对象,以满足频繁创建和销毁小对象的需求。这些分配器可以高效地管理小块内存,避免了传统内存分配时的开销。 Linux内存管理的...
其中包括物理内存及其架构独立性的概述、伙伴系统的各种操作(例如初始化和分配)、slab/slab/slub分配器的不同层面的工作机理以及内存的节点化管理和分配方法,详尽解释了一系列重要的数据结构,揭示Linux内存高效...
SLUB(Simple List-Based Unified Buffer)是Linux内核中用于内存管理的一种高效数据结构,它在SLAB(Simple Linear Allocator for Buffers)的基础上进行了优化,旨在提高内存分配和释放的性能。SLUB的设计目标是...
在Linux系统中,内存管理包括了多种机制和数据结构,如slub内存分配器、页(frame)管理、缓存(kmem_cache)等。以下是对这些关键知识点的详细说明: 1. 常见结构体 - `struct kmem_cache`: 这个结构体是Linux内核中...
小内存分配使用 slub 分配,slub 将几个页单独拎出来作为缓存,里面维护了链表。 三、虚拟地址的组织 虚拟地址对应的是虚拟空间,虚拟空间只不过是一个虚拟地址的集合,用来映射物理内存。虚拟空间分为用户态和...
总的来说,Linux内存管理是一个复杂的系统,它通过精细的算法和数据结构来实现高效、低碎片的内存分配。理解这些概念和机制对于优化系统性能、调试内核问题以及开发高效的应用程序至关重要。通过深入学习Linux内存...
- Linux内存管理以页为单位进行分配,每个进程有自己的页表,用来映射虚拟地址到物理地址。页表的使用减少了内存访问的开销。 4. **内存分配策略**: - 包括匿名内存(如堆)和文件映射内存(如共享库)。匿名...
此外,SLAB、SLUB和SLOB分配器进一步优化了内存分配,允许在一个页面内独立分配多个小块内存,有效减少了内部碎片。 内存管理层次关系图展示了从用户空间到内核空间的内存分配流程,包括kmalloc、slab分配器、页表...
Linux内存管理是Linux操作系统的一个核心组成部分,它负责控制计算机系统中的物理和虚拟内存资源。在Linux 3.10版本内核中,内存管理涵盖了一系列复杂的子系统和机制,如物理内存布局的初始化、伙伴系统、slab分配器...
Linux系统提供了多种内存分配算法,例如,SLAB、SLUB、SLOB等。不同的算法对系统性能有不同的影响。选择合适的内存分配算法可以提高系统性能。 2.3 缩小内存碎片 内存碎片是指内存中存在多个小的空闲块,导致系统...
buddy/slub是Linux内核中的内存管理算法。buddy防止内存的“外碎片”,即防止内存块越分越小,而不能满足大块内存分配的需求。slub防止内存的“内碎片”,即尽量按请求的大小分配内存块,防止内存块使用上的浪费。...
为了缓解这个问题,Linux引入了SLAB、SLUB和SLOB分配器,它们在同一个页面内管理多个小内存块,提高了内存的使用效率。 内存管理的层次结构图展示了不同级别的内存分配策略,如kmalloc处理小内存分配,slab分配器在...
《基于ARM CPU的Linux物理内存管理》 在现代计算机系统中,内存管理是至关重要的一个环节,尤其是在嵌入式系统中,如基于ARM架构...掌握这些知识对于进行Linux内核开发、系统优化或者解决内存相关问题具有极大的价值。
总结来说,Linux内核内存分配器是一个复杂而精细的系统,它通过内存池、位图、链表以及专门的分配器如Slab、Slub和Slob,确保了内核内存的高效、低碎片和安全分配。了解这些概念对于理解和优化Linux内核的性能至关...
Slab管理器的引入解决了传统内存分配方法中可能导致的浪费和低效问题。 在Linux内核中,有许多数据结构,如struct inode和struct dentry,它们在需要时动态创建,当不再使用时需要被释放。如果简单地使用alloc_...