“内存碎片化”还存在问题吗? [关闭]

问题描述 投票:6回答:2

我有点困惑。在操作系统课程中,我们被告知所有操作系统都通过分页或分段来处理内存碎片,并且根本没有连续的物理内存分配。 OS使用不同级别的寻址(逻辑/物理)来避免连续的内存分配。现在here有很多关于它的讨论。我的问题是:在支持逻辑寻址的操作系统的c ++编程中,这个问题是否真实存在(任何进程是否因为内存碎片而崩溃)?如果是的话,为什么首先每个操作系统都试图避免连续寻址?

c++ memory-management memory-fragmentation
2个回答
6
投票

有两层:虚拟进程地址空间中的碎片和物理内存中的碎片。

如果您查看任何现代应用程序,您可以看到其内存使用量随着内存未发布到操作系统而增长的情况。你可以说这是由其他因素引起的,但内存碎片(例如分配的内存块的非连续位置)是这个的核心原因。简而言之,内存分配器拒绝向操作系统释放内存。

如果您对物理内存中的碎片感兴趣,那么即使在页面中组织了内存,仍然需要分配物理上连续的内存块。例如,如果您需要避免虚拟内存开销,则可能需要使用大页面(就Linux而言是“大页面”)。 x86_64支持4KiB,2MiB和1GiB页面。如果没有所需大小的连续物理内存,您将无法使用它们。

如果操作系统是指“内核”,那么它无法帮助您处理进程地址空间中发生的碎片(堆碎片)。 C库应该尽量避免碎片,不幸的是,它并不总是能够这样做。请参阅链接的question

如果至少分配了一些内存,内存分配器通常无法释放大块内存。有一个部分解决方案可以利用页面中的虚拟内存组织 - 所谓的“懒惰”机制由Linux和BSD上的MADV_FREE和Windows上的DiscardVirtualMemory代表。当你有一大块内存只是部分使用时,你可以通知内核不再需要那部分内存,它可以在内存压力下恢复。这是懒惰地完成的,并且仅在内存压力下完成,因为内存释放非常昂贵。但是由于性能原因,许多内存分配器仍然不使用它。

所以你的问题的答案 - 这取决于你对程序效率的关注程度。大多数程序都不关心,因为标准分配器只为它们完成工作。当标准分配器无法有效地完成其工作时,某些程序可能会受到影响。


3
投票

操作系统不会避免连续的内存分配。在顶层,您有硬件和软件。在这种情况下,硬件资源有限,物理内存。为了共享资源并避免用户程序处理它的共享,发明了虚拟寻址层。它只是将连续的虚拟寻址空间映射到稀疏的物理区域。换句话说,0x10000虚拟地址可以在一个进程中指向0x80000物理地址,在另一个进程中指向0xf0000。

分页和交换意味着将一些页面或整个应用程序内存写入磁盘,然后在某些时候将其恢复。它之后很可能会有不同的物理页面映射。

因此,您的程序将始终看到连续的虚拟寻址空间,这在物理硬件空间中确实是碎片化的。顺便说一下,它是以恒定的块大小完成的,并且没有浪费或未使用的内存孔。

现在,由new / malloc函数引起的第二级碎片,它与您分配和删除不同大小的内存这一事实有关。这会将您的堆分散到虚拟空间中。这些功能确保尽可能少的浪费。

因此,在您的通用C ++(或任何其他语言)编程中,您不关心任何内存碎片。您分配的所有块都保证在虚拟空间中是连续的(不一定是物理的)。

© www.soinside.com 2019 - 2024. All rights reserved.