news 2026/5/1 9:50:53

引导内存分配器 Buddy 分配器的关系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
引导内存分配器 Buddy 分配器的关系

引导内存分配器 Buddy 分配器的关系

在 Linux 内核启动的早期阶段,物理内存管理面临着一个“鸡生蛋,蛋生鸡”的问题:内核需要分配内存来初始化用于内存管理的数据结构(如struct page数组),但此时完善的 Buddy 分配器尚未建立。为了解决这个问题,内核引入了简单的引导内存分配器

一、为什么需要引导内存分配器?

在内核启动初期,内存管理子系统尚未初始化完成,主要面临以下挑战:

  1. 元数据未就绪:描述物理内存的mem_map(页描述符数组)尚未分配和初始化。
  2. Buddy 系统未工作:Buddy 算法依赖于struct zonestruct page等结构,在这些结构就绪前无法工作。
  3. 早期分配需求:内核在初始化阶段就需要分配内存,例如用于存放内核页表、设备树(Device Tree)解析结果、initrd 镜像等。

因此,内核需要一个简单、临时的内存分配机制,这就是引导内存分配器。它仅在启动阶段工作,一旦 Buddy 系统初始化完成,引导内存分配器就会将管理权移交出去并退役。

二、两种引导内存分配器:bootmem 与 memblock

随着 Linux 内核的发展,引导内存分配器也经历了演变。

1. bootmem 分配器 (旧架构)

bootmem是较早期的引导内存分配器,主要利用一个位图(bitmap)来管理内存。

  • 原理:使用一个位图,每一位代表一个物理页。如果该位为 1,表示该页已被占用;为 0 表示空闲。
  • 分配:采用最先适配算法(First Fit),扫描位图找到足够大的连续空闲区域。
  • 缺点
    • 位图本身需要占用内存,且随着内存容量增大,位图变得很大。
    • 在大型系统(如 NUMA)中,管理多个节点的 bootmem 结构复杂。
  • 现状:ARM64 架构内核已不再使用bootmem,但其他一些处理器架构仍在使用。

2. memblock 分配器 (新架构)

memblock是目前主流(包括 ARM64)使用的引导内存分配器,用于替代bootmem

  • 数据结构:它维护两个列表(数组):
    • memory:描述系统所有可用的物理内存范围。
    • reserved:描述已经被预留、占用的内存范围。
  • 原理
    • memblock不使用庞大的位图,而是直接管理“内存区域(Region)”的数组。
    • 当需要分配内存时,它在memory列表中查找空闲空间,并将其添加到reserved列表中。
  • 优点
    • 结构更紧凑,开销小。
    • 支持从设备树(DTS)直接获取内存布局信息。
    • 支持热插拔(Hotplug)和复杂的 NUMA 配置。
    • memblock_add添加内存,memblock_remove移除内存,memblock_alloc分配内存。

三、引导分配器与 Buddy 分配器的交接

引导内存分配器是一个临时的“管家”,它的最终使命是将内存管理权平稳过渡给 Buddy 分配器。这个过程发生在内核初始化函数mm_init()流程中。

交接流程:

  1. 收集内存信息

    • 内核启动时,首先通过解析设备树(DTS)或 BIOS/UEFI 获取物理内存布局。
    • 调用memblock_add()将物理内存范围注册到引导分配器中。
  2. 早期分配服务

    • 在 Buddy 系统建立前,内核各子系统的内存申请(如页表分配)都由memblock_alloc()处理。
  3. 协助建立 Buddy 结构

    • 内核利用引导分配器分配的内存,来创建和初始化 Buddy 系统所需的关键数据结构,主要是mem_map(存放所有的struct page)。
  4. 释放空闲内存给 Buddy

    • 当 Buddy 系统的数据结构初始化完成后,内核会调用类似memblock_free_all()free_all_bootmem()的函数。
    • 核心动作:遍历引导分配器中发现的所有未使用的空闲页,将它们逐个(或成块)释放给 Buddy 系统(通过调用__free_pages等接口)。
    • 此时,这些页会被标记为空闲,挂入 Buddy 系统的free_area链表中,正式成为 Buddy 系统的可分配资源。
  5. 引导分配器退役

    • 一旦空闲内存全部移交完毕,引导分配器的数据结构本身所占用的内存也会被释放(如果可能),或保留作为存根。
    • 此后,所有的内存申请(包括内核和用户空间)都必须通过 Buddy 分配器(如alloc_pages,kmalloc)进行。

四、总结

特性引导内存分配器 (memblock/bootmem)Buddy 分配器
生命周期仅限于内核启动早期内核初始化完成后一直运行
管理粒度粗粒度的物理地址范围精细的页框 (Page Frame)
算法复杂度简单(线性扫描/数组管理)复杂(阶梯链表、反碎片、LRU等)
主要职责1. 临时响应早期分配请求
2. 协助初始化 Buddy 的元数据
3. 将空闲内存移交给 Buddy
系统运行时的通用物理内存管理

简而言之,引导内存分配器是 Buddy 分配器的前置加载器。它在荒芜的物理内存上建立起最基础的秩序,为构筑宏大的 Buddy 内存帝国铺平道路,并在完成使命后功成身退。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 5:48:08

Buddy分配器

Buddy分配器 1. 内核在基本的伙伴分配器基础改进扩展 支持内存节点和区域,称为分区的伙伴分配器(zoned buddy allocator)。 为了预防内存碎片,把物理页框通过移动性分组。 针对分配单页做了性能优化,为了减少处理器锁的…

作者头像 李华
网站建设 2026/5/1 8:45:41

【项目中的经验总结】

知识点一:多电源域下 Dummy Gate 的连接问题 1. 背景说明 在 MOS 管版图中,dummy gate 常用于满足工艺对栅极密度、对称性和边缘效应的要求。 Dummy gate 虽不参与功能,但仍具有栅氧层及栅-源 / 栅-漏寄生电容,不能视为“完全无效…

作者头像 李华
网站建设 2026/5/1 9:12:22

线性规划:库存切割问题

原文:towardsdatascience.com/linear-programming-the-stock-cutting-problem-dc6ba3bf3de1 本文深入探讨了线性规划如何解决一个称为“库存切割”的具体问题。在深入探讨本系列中的线性规划细节之前,我想提供一个具体的例子。本文将使用未在本文中定义的…

作者头像 李华
网站建设 2026/5/1 4:59:53

国抽对接规则

1、国抽可以同步下来 待填报之前的样品信息(包括正在接样状态)。 2、国抽可以同步下来 待填报且已维护基础表的项目信息(基础表维护按照报送分类B及细类维护,或特殊样品的项目维护)。

作者头像 李华
网站建设 2026/4/23 15:04:21

[特殊字符]️_开发效率与运行性能的平衡艺术[20260107171443]

作为一名经历过无数项目开发的工程师,我深知开发效率与运行性能之间的平衡是多么重要。在快节奏的互联网行业,我们既需要快速交付功能,又需要保证系统性能。今天我要分享的是如何在开发效率和运行性能之间找到最佳平衡点的实战经验。 &#…

作者头像 李华
网站建设 2026/5/1 5:46:09

c++ 17的std::variant对标c#的哪个类型

C# 的 System.Object、dynamic 和 C# 7.0 引入的 System.ValueTuple 以及 System.OneOf 等都可以实现类似功能,但最接近 C std::variant 语义的是:1. 官方方案:System.Object 和模式匹配(最接近)基础用法csharp// 类似…

作者头像 李华