Linux 内存分配器的工作方式是将物理内存中的页面映射到虚拟内存。它可以将物理内存中的连续区域或稀疏块映射到虚拟内存中的连续区域。
使用伙伴算法,物理内存可以排列成连续的页面集(我们称之为存储桶)。一个存储桶中包含的页面数始终是 2 的幂,因为这样可以轻松地将较小的存储桶分组到一个大存储桶中(例如,1 个页面组成一个顺序 0 存储桶,2 个顺序 0 存储桶组成一个顺序 1 存储桶,2 个顺序 1 存储桶组成一个顺序 2 存储桶,等等)。
随着时间的推移,物理内存会变得碎片化,以至于不再可能分配一定大小的存储桶,因此内核被迫分配分散在物理内存中的较小的存储桶。
问题是:Linux 内核是否会实时重新排列这些存储桶,以增加更大存储桶可用的概率?如果是这样,它是如何实现的?
答案1
您在这里描述的是 Linux 内核中使用的内存分配,而不是按页面进行的进程 RAM 分配。
此算法处理少量内存,最多为一页大小。只有在现代内核中,请求才有可能大于一页。
据我所知,内核不会重新安排内存,这意味着没有垃圾收集,因为某些分配的对象在被关键进程使用时可能无法移动。
当内存过于碎片化而无法分配请求的量时,内核可以执行以下操作之一:
- 由于没有可用内存,请求失败。
- 将请求安排在稍后执行,希望伙伴系统能够处理碎片。这仅适用于内核的非关键部分。
- 关键子系统可能从一开始就分配一块内存,以自行管理其分配。
- 一些内核内存可能是可交换的,并且如果优先级较高的例程请求的话,这些内存将被写出。
编写内核软件的基本规则是,在未保证完成所需的资源的情况下,不要承诺执行。编写良好的内核例程将在启动之前首先分配所有资源,包括内存。这将避免回溯和保存旧状态的需要,如果在例程已经完成一些工作后发生错误,则需要保存旧状态,因此现在在返回失败条件之前,它必须撤消所做的一切。
有关详细信息,请参阅 Linux Journal 文章 内存分配。