3

我正在阅读一些实时操作系统规范,我读到在 RTOS 中,我们通常不喜欢使用 malloc。这样做的原因是:出于性能问题,我们不应该使用 malloc,因为通过 malloc 分配内存非常耗时,而且跟踪分配的内存的开销也更高。

现在在实时系统中,所有进程都有时间限制,我们一般不使用malloc。我很好奇并开始研究一些类似于在 RTOS 运行时实际分配内存的方式,然后我发现了内存池。现在有人写道,内存池实际上意味着固定大小的块分配。现在内存池的优点是它不会受到碎片的影响。这怎么可能?假设我们有 3 个 4 字节的池,而应用程序需要 10 字节,那么在这种情况下,内存池将受到内部碎片的影响。

内存池如何工作以及如何分配内存?应用程序是否在编译时获得池,就像特定应用程序将从 4 字节的池大小中获得 3 个池一样?如果他们需要的内存无法放入池中怎么办。这样的系统中是否存在许多不同大小的内存池?请给我解释一下。

4

2 回答 2

1

那么,碎片将取决于内存池的实现。通常,内存池是固定大小的内存块池。当某些东西想要一块这样大小的内存时,它就会进入那个池。因此,没有碎片,因为所有想要该大小的块的东西都是从该大小的块池中获取的。

现在,如果不存在特定大小的块池,则可以使用更大大小的块池。如果发生这种情况,那么技术上就会存在碎片,因为分配的内存块的某个部分没有被使用(碎片化)。

如果所有内存池都提供了所有所需大小的块,那么就不会有碎片。

于 2012-09-22T15:41:09.080 回答
0

池不会消除碎片,但它们可以显着减少碎片,并且还可能减少分配大量非常小的块的开销。一个好的方案是一个库,它允许客户端代码为其每个高度缩放的结构创建一个池。在创建池时,您指定块大小、最初分配和增长的块数,以及用于调试的文本名称。

要分配块,请将池 ID 传递给分配器。只要池中没有空闲块,它就会分配一块连续的块并使其可用,并返回其中一个。每当一个块被释放时,如果该块的块中的所有块都是空闲的,它就会释放该块。

对于调试,有一个打印所有池的例程,给出描述、分配的数量以及可能的其他统计信息,例如可用的空闲池的数量(如果这很高,则存在碎片问题)和曾经分配的最大值。对查找内存泄漏非常有帮助。

对于这种类型的库,最坏的情况是子系统在系统生命周期的早期分配大量块,然后随机释放其中的大部分。许多块将保持分配状态,但使用中的块很少。最好的情况(与 malloc 相比)是需要具有广泛不同生命周期的新块的持续循环,对于必须长时间保持运行的系统,如某些嵌入式系统。

这是最简单的,最适合单线程应用程序。对于多线程应用程序,必须注意使其线程安全,并且您可能需要模仿 malloc() 经常在幕后进行的优化以最小化锁定开销(例如,每个线程的“竞技场”)。

于 2016-12-02T04:35:01.483 回答