通过阅读“understanding linux network internals”和“understanding linux kernel”这两本书以及其他参考资料,我很困惑,需要对“内存缓存”和“内存池”技术进行一些澄清。
1)它们是相同的还是不同的技术?
2)如果不相同,是什么造成了差异或不同的目标?
3) 另外,Slab Allocator是怎么进来的?
通过阅读“understanding linux network internals”和“understanding linux kernel”这两本书以及其他参考资料,我很困惑,需要对“内存缓存”和“内存池”技术进行一些澄清。
1)它们是相同的还是不同的技术?
2)如果不相同,是什么造成了差异或不同的目标?
3) 另外,Slab Allocator是怎么进来的?
关于slab分配器:
因此,想象一下内存是平坦的,即您有一块 4 gigs 连续内存。然后您的一个程序需要 256 字节的内存,因此内存分配器必须从这 4 个演出中选择一个合适的 256 字节块。所以现在你的记忆看起来像
<============256bytes=======================>
(每个 = 是一个连续的内存块)。一段时间过去了,许多使用内存运行的程序需要更多或更多或更少的 256 个块,因此最终您的内存可能如下所示:
<==256==256=256=86=68=121===>
所以它变得支离破碎,然后就没有你美丽的 4gig 内存块的痕迹——这就是碎片化。现在,slab 分配器要做的是跟踪分配的对象,一旦它们不再使用,它会说内存是空闲的,而实际上它将保留在某种列表中(您可能想了解FreeLists)。
所以现在想象一下,第一个程序放弃分配的 256 个字节,然后一个新程序想要拥有 256 个字节,因此它可能会重新使用最后释放的 256 个字节而不是分配一个新的主内存块,而不必经历负担在物理内存中搜索适当的连续空间块。这就是您实质上实现内存缓存的方式。这样做是为了整体减少内存碎片,因为您最终可能会遇到内存碎片太大以至于无法使用的情况,并且内存管理器必须做一些魔术来让您获得适当大小的块。使用平板分配器可以主动解决(但不能消除)问题。
Lookaside Caches - Linux 内核中的缓存管理器有时称为slab 分配器。您最终可能会一遍又一遍地分配许多相同大小的对象,因此通过使用这种机制,您可以分配许多相同大小的对象,然后在以后使用它们,而无需一遍又一遍地分配许多对象。
内存池只是一种后备缓存的形式,它试图始终保留一个内存列表以备不时之需,因此当创建内存池时,分配函数(slab allocators)会创建一个预分配对象池,以便您可以获取它们当你需要的时候。
Linux 内存分配器 AKA 平板分配器维护经常使用的类似或近似大小的内存对象列表/池。平板为程序员提供了额外的灵活性,可以创建自己的相同大小的常用内存对象池,并将其标记为程序员想要的,分配,解除分配并最终销毁它。这个缓存是你的驱动程序知道的,它是私有的。但是有一个问题,在内存压力期间,分配失败的可能性很高,这在某些驱动程序中是不可接受的,那么更好的办法是始终保留一些方便的内存,这样我们就不会感到内存紧缩,因为 kmem 缓存是更通用的池机制,我们需要一个能够始终保持最低所需内存的人,这就是我们的伙伴内存池。