news 2026/5/30 11:34:27

引导内存分配器 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/23 5:47:07

系列教程十四 | 基于CosyVoice 2.0实现语音风格迁移

一.背景介绍 随着生成式人工智能的快速发展,语音合成(Text-to-Speech, TTS)技术正在迈向更自然、更智能、更具情感表达的新时代。过去的 TTS 模型虽然已在音质和语义准确度方面取得显著进步,但在跨语言、情感表达、个性化模拟等方…

作者头像 李华
网站建设 2026/5/20 16:01:37

Agent2Agent (A2A) Protocol( A2A 协议)简介、组件

Agent2Agent (A2A) Protocol(简称 A2A 协议)是旨在让不同 AI 代理(agents)之间互联互通、协作的开放标准。内容包括协议的主要组件(building blocks)、各组件作用,以及这些组件在一个典型流程中…

作者头像 李华
网站建设 2026/5/20 11:23:43

Python设计模式:享元模式详解

享元模式的核心思想享元模式(Flyweight Pattern)通过共享对象减少内存占用,适用于存在大量重复对象的场景。其核心是将对象的内在状态(可共享)与外在状态(不可共享)分离,通过共享内在…

作者头像 李华
网站建设 2026/5/20 18:11:58

线性化注意力

原文:towardsdatascience.com/linearizing-attention-204d3b86cc1e?sourcecollection_archive---------3-----------------------#2024-12-26 打破二次方限制:softmax 注意力的现代替代方案 https://medium.com/shitanshu273?sourcepost_page---bylin…

作者头像 李华
网站建设 2026/5/29 12:18:39

LibGDX中的多边形绘制优化

在游戏开发中,绘制多边形是常见的任务之一。特别是当我们需要处理复杂的形状或大量的点时,性能和错误处理就显得尤为重要。本文将通过一个具体的实例,讨论如何在LibGDX中优化多边形的绘制,并避免常见的IndexOutOfBoundsException错误。 问题背景 当使用LibGDX的ShapeRend…

作者头像 李华