当前位置: 首页 > article >正文

深入剖析 memblock:Linux 内核早期内存管理的核心机制

1. memblockLinux内核启动时的临时工刚接触Linux内核开发的朋友可能会好奇在系统启动的最初阶段伙伴系统Buddy System还没准备好接管内存管理时内核是如何分配内存的这就不得不提到我们今天的主角——memblock。这个看似简单的内存分配器在内核启动过程中扮演着关键角色。我刚开始研究内核启动流程时发现memblock就像是个临时工。它在系统启动早期负责收集和管理物理内存等伙伴系统这个正式工上岗后就把所有工作交接出去自己功成身退。这种设计非常巧妙既解决了启动阶段的内存管理需求又不会给后续系统运行带来额外负担。memblock的工作流程可以简单概括为三个步骤收集从设备树、BIOS-e820等不同来源获取物理内存信息管理在启动阶段提供内存分配、预留等功能交接将可用内存全部释放给伙伴系统后自行退出2. memblock的接口设计简单却强大2.1 内存管理的基础操作memblock提供的接口可以分为四大类每类都有其特定的用途。让我用一个实际项目中的例子来说明在为嵌入式设备移植Linux内核时我们需要预留一段内存给专用硬件使用。这时就会用到memblock_reserve接口// 预留从0x30000000开始的16MB内存 memblock_reserve(0x30000000, 0x1000000);这个简单的调用就能确保这段内存不会被其他代码意外使用。类似的常用接口还有内存添加memblock_add内存移除memblock_remove内存分配memblock_alloc内存释放memblock_free2.2 内存分配的艺术memblock的内存分配接口设计得非常灵活。以memblock_alloc_range为例phys_addr_t memblock_alloc_range(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end, enum memblock_flags flags);这个接口允许你指定要分配的内存大小size对齐要求align分配范围start-end特殊标志flags我曾经在一个项目中遇到需要从特定地址范围分配对齐内存的情况这个接口就派上了大用场。值得注意的是如果align参数为0内核会默认使用SMP_CACHE_BYTES在aarch64上是64字节作为对齐值并发出警告。2.3 遍历内存域memblock提供了多种遍历内存域的方法这对于系统初始化阶段的内存映射特别有用。例如#define for_each_free_mem_range(i, nid, flags, p_start, p_end, p_nid) \ for_each_mem_range(i, memblock.memory, memblock.reserved, \ nid, flags, p_start, p_end, p_nid)这个宏会遍历所有可用的内存区域自动避开预留区域。在内核启动过程中正是通过这些遍历接口完成了线性映射等重要工作。3. memblock的内部数据结构剖析3.1 核心数据结构关系memblock的内部数据结构设计得非常精妙。核心是三个层级struct memblock全局管理器struct memblock_type内存类型分类struct memblock_region具体内存区域这种层级设计使得内存管理既清晰又高效。让我用一个生活中的例子来比喻memblock就像一个大仓库struct memblock里面分成了几个区域struct memblock_type每个区域又摆放着不同大小的货物struct memblock_region。3.2 关键数据结构详解struct memblock是最高层的管理结构struct memblock { bool bottom_up; // 分配方向 phys_addr_t current_limit; // 当前分配限制 struct memblock_type memory; // 所有内存 struct memblock_type reserved; // 预留内存 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP struct memblock_type physmem; // 物理内存映射 #endif };其中memory和reserved的关系特别重要memory记录所有物理内存reserved记录已被占用的内存。当需要分配内存时memblock会从memory中找但要避开reserved区域。3.3 内存区域属性每个内存区域都有丰富的属性标记enum memblock_flags { MEMBLOCK_NONE 0x0, // 默认值 MEMBLOCK_HOTPLUG 0x1, // 可热插拔 MEMBLOCK_MIRROR 0x2, // 镜像区域 MEMBLOCK_NOMAP 0x4, // 不添加到内核直接映射 };这些属性在内核启动过程中被广泛使用。比如MEMBLOCK_NOMAP标记的内存区域不会被映射到线性地址空间这在处理特殊硬件寄存器时非常有用。4. memblock的核心算法逻辑4.1 内存区域的合并与裁剪memblock在处理内存区域时有两个关键操作合并相邻区域和裁剪超出限制的区域。合并操作主要发生在以下情况添加新内存区域时修改内存区域属性时合并算法会检查相邻区域是否地址连续属于同一个NUMA节点具有相同属性标记如果满足条件就会将它们合并为一个更大的区域。这个过程就像把相邻的空地合并成一块更大的土地便于后续管理。4.2 动态数组扩容机制memblock使用静态定义的数组来存储内存区域信息但设计时考虑到了动态扩容的需求static int __init_memblock memblock_double_array(struct memblock_type *type, phys_addr_t new_area_start, phys_addr_t new_area_size) { // 1. 检查是否允许扩容 // 2. 计算新旧数组大小 // 3. 尝试分配新数组 // 4. 拷贝数据到新数组 // 5. 释放旧数组 // 6. 预留新数组占用的内存 }这个扩容过程虽然看起来简单但在内核启动早期阶段实现起来却很有挑战性因为这时还没有完整的动态内存管理机制可用。4.3 内存分配的核心算法memblock_find_in_range_node是内存分配的核心函数它实现了两种分配策略自底向上分配适合普通内存自顶向下分配适合特殊需求算法会根据以下因素选择最佳策略当前分配方向设置bottom_up内核镜像位置请求的分配范围我曾经遇到过一个性能问题通过调整分配策略将关键数据结构的分配方向改为自顶向下获得了明显的性能提升。5. memblock在ARM64启动过程中的应用5.1 内存的初始扫描与添加在ARM64架构中memblock的初始化始于设备树解析。内核会扫描设备树中的memory节点获取系统物理内存信息early_init_dt_scan_memory() { // 1. 查找memory类型节点 // 2. 读取linux,usable-memory或reg属性 // 3. 解析内存范围和属性 // 4. 调用memblock_add添加内存 // 5. 处理热插拔标记 }这个过程就像系统启动时做的人口普查先搞清楚自己有多少家底内存资源。5.2 内存预留的关键步骤在arm64_memblock_init函数中内核会进行一系列关键的内存预留操作保留内核镜像占用的内存处理initrd内存区域保留线性映射无法覆盖的内存处理命令行指定的内存限制保留crash kernel使用的内存这些预留操作确保了关键系统资源不会被普通内存分配占用就像在仓库中提前划出特定区域存放重要物资。5.3 从memblock到伙伴系统的过渡当伙伴系统准备就绪后内核会调用memblock_free_all释放所有可用内存void __init memblock_free_all(void) { // 遍历所有空闲内存区域 for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, start, end, NULL) { // 将内存释放给伙伴系统 __free_memory_core(start, end); } }这个过程就像把临时仓库中的货物移交给正式仓库管理系统。之后memblock的使命就基本完成了但它保留的数据结构仍会被用于一些特殊检查比如pfn_valid判断物理页框是否有效。通过深入分析memblock的设计与实现我们不仅能更好地理解Linux内核启动过程还能从中学习到优秀的内存管理设计思想。这些知识对于内核开发、系统调优以及解决内存相关的问题都非常有帮助。

相关文章:

深入剖析 memblock:Linux 内核早期内存管理的核心机制

1. memblock:Linux内核启动时的"临时工" 刚接触Linux内核开发的朋友可能会好奇:在系统启动的最初阶段,伙伴系统(Buddy System)还没准备好接管内存管理时,内核是如何分配内存的?这就不…...

2026年OpenClaw(Clawdbot)阿里云/本地喂饭级安装、配置大模型Coding Plan及使用步骤【最全】

2026年OpenClaw(Clawdbot)阿里云/本地喂饭级安装、配置大模型Coding Plan及使用步骤【最全】。本文面向零基础用户,完整说明在轻量服务器与本地Windows11、macOS、Linux系统中部署OpenClaw(Clawdbot)的流程&#xff0c…...

C# 结合pcap驱动实现EtherCAT主站开发实战

1. 为什么选择C#开发EtherCAT主站? 提到工业通信协议开发,很多人第一反应就是C/C。确实,像SOEM、IGH这些主流EtherCAT主站都是用C语言开发的。但作为一个长期在工业自动化领域摸爬滚打的开发者,我发现用C#开发EtherCAT主站有几个独…...

2026年OpenClaw(Clawdbot)本地环境4分钟本地喂奶级部署及使用流程【亲测】

2026年OpenClaw(Clawdbot)本地环境4分钟本地喂奶级部署及使用流程【亲测】。本文面向零基础用户,完整说明在轻量服务器与本地Windows11、macOS、Linux系统中部署OpenClaw(Clawdbot)的流程,包含环境配置、服…...

Matlab与CarSim联合仿真:基于三自由度车辆模型搭建EKF/UKF与积分法融合测量质心...

matlab和carsim联合仿真,基于三自由度车辆模型,搭建ekf或者ukf与积分法融合的用于测量质心侧偏角,纵向速度,横摆角速度。 清晨六点半的实验室键盘声格外清脆,我盯着屏幕里那辆在CarSim里蛇形走位的虚拟高尔夫&#xf…...

从理论到实践:共射极放大电路的设计与调试全攻略

1. 共射极放大电路的核心原理 共射极放大电路之所以被称为"电子工程师的必修课",关键在于它完美展现了晶体管放大的本质。想象一下,你正在用麦克风唱歌,但声音太小无法让全场听到——这时候就需要一个"声音放大器"。共射…...

自动化编译VTK库:用CMake脚本一键搞定源码下载、编译与集成

自动化编译VTK库:用CMake脚本一键搞定源码下载、编译与集成 在大型可视化项目开发中,VTK(Visualization Toolkit)作为行业标准的科学计算可视化库,其环境配置往往成为团队协作的瓶颈。传统手动编译方式不仅耗时费力&am…...

突破微信OAuth2.0单回调域名限制的实战方案

1. 微信OAuth2.0单回调域名限制的痛点 做过微信网页开发的同行应该都遇到过这个经典问题:在微信公众平台配置网页授权域名时,一个公众号只能设置一个回调域名。这个限制对于单一应用场景影响不大,但当我们需要同时运营多个子站点或微官网时&a…...

Qt原子变量避坑指南:从QAtomicFlag到QAtomicPointer,这些内存顺序和ABA问题你搞明白了吗?

Qt原子变量深度避坑指南:从内存顺序到ABA问题的实战解析 在Qt多线程开发中,原子变量就像一把双刃剑——用得好可以大幅提升性能,用不好则会引入难以调试的幽灵问题。上周团队就遇到一个典型案例:在ARM服务器上运行良好的无锁队列&…...

CSS如何在开发环境下自动热更新样式_配置webpack-dev-server

要让 CSS 热更新生效,必须同时启用 HMR(devServer.hot: true)、使用 style-loader(非 MiniCssExtractPlugin.loader)处理 CSS、且开发环境禁用 MiniCssExtractPlugin。webpack-dev-server 怎么配才能让 CSS 热更新生效…...

UniApp打包小程序,从‘巨无霸’到‘苗条身材’的完整瘦身方案(HBuilderX CLI双版本指南)

UniApp打包小程序,从‘巨无霸’到‘苗条身材’的完整瘦身方案(HBuilderX & CLI双版本指南) 在移动互联网时代,小程序因其轻量级特性而广受欢迎,但这也意味着对包大小的严格限制。当UniApp项目逐渐壮大&#xff0c…...

一篇 EI 论文从初稿到录用,我复盘了全过程

很多同学第一次投 EI 会议都很慌:不知道论文要写到什么程度、格式怎么改、审稿人会问什么、被拒了怎么办。这篇就把我从 0 初稿→返修→录用的完整流程完整复盘一遍,不搞玄学、不讲空话,全程可照抄执行,适合第一次冲 EI 的硕博生直…...

PKHeX自动合法性插件:告别繁琐验证,拥抱智能数据管理

PKHeX自动合法性插件:告别繁琐验证,拥抱智能数据管理 【免费下载链接】PKHeX-Plugins Plugins for PKHeX 项目地址: https://gitcode.com/gh_mirrors/pk/PKHeX-Plugins 你是否曾为宝可梦数据的合法性验证而烦恼?面对复杂的个体值、技能…...

Win11 更新后卡顿 / 异常?官方教程教你安全卸载更新(附视频)

不少联想电脑用户在升级 Win11 系统更新后,会遇到电脑卡顿、软件闪退、驱动异常、续航变差等问题,即便重启也无法改善,严重影响日常办公与使用体验。面对这类情况,很多用户不知道如何正确回退系统更新,要么盲目操作导致…...

IJIS投稿实战:从Latex排版到审稿回复的保姆级避坑指南

IJIS投稿实战:从LaTeX排版到审稿回复的避坑指南 第一次向IJIS(International Journal of Intelligent Systems)投稿时,我踩遍了从模板选择到审稿回复的所有坑。这篇指南将分享如何避开这些陷阱,让你的投稿过程更加顺畅…...

Debian 12 上配置 containerd 的优化实践与生产环境调优

1. 为什么选择 containerd 作为容器运行时? 在容器化技术领域,containerd 已经成为事实上的行业标准运行时。相比完整的 Docker 引擎,containerd 去掉了非必要的组件,只保留核心的容器生命周期管理功能。这种精简设计带来的直接好…...

ARM开发板实战:用官方工具链交叉编译OpenSSL 1.1.1k的避坑指南

ARM开发板实战:官方工具链交叉编译OpenSSL 1.1.1k的深度解析 在嵌入式开发领域,为ARM架构设备编译OpenSSL是一个常见但充满挑战的任务。不同于x86平台的直接编译,交叉编译过程中会遇到各种ABI兼容性、工具链配置和参数优化问题。本文将深入探…...

10、从文档上传到答案生成:一篇讲透 RAG 系统完整流程

很多人第一次接触 RAG,会先记住一句话: 先检索,再生成。 这句话当然没错,但如果你真的开始做一个知识库问答系统,很快就会发现: 真正把系统跑起来,远远不只是“检索一下,再调个模型”这么简单。 因为用户看到的只是一个输入框和一个答案,系统背后其实已经走过了一整…...

微信小程序登录实战:从OpenID到UnionID的高效获取与应用

1. 微信小程序登录流程的核心概念 第一次接触微信小程序登录时,我被OpenID和UnionID这两个概念绕得头晕。后来在实际项目中踩过几次坑才明白,它们其实是微信生态中用户身份识别的关键。简单来说,OpenID就像是你家小区的门禁卡,只能…...

STM32G030F6 + RT-Thread 驱动 WS2812B 全彩灯环:从硬件连接到代码解析

STM32G030F6 RT-Thread 驱动 WS2812B 全彩灯环:从硬件连接到代码解析 在嵌入式开发领域,将微控制器与智能LED灯环结合使用,可以创造出令人惊艳的视觉效果。STM32G030F6作为一款性价比极高的ARM Cortex-M0内核微控制器,配合RT-Thr…...

国芯筑基驭智城,第二届酒仙桥论坛解锁“十五五”产城AI增长新范式

4月15日,2026酒仙桥论坛在北京国家会议中心、北京数字经济算力中心同步启幕,以“国芯AI驭未来”为主题,聚焦AI赋能地方发展、驱动产业创新、引领技术突破等关键议题,共探智能经济新形态实践路径,凝聚中国AI产业高质量发…...

DeepSeekMine RAG实战:我把公司项目文档塞进去,问了100个问题后总结的避坑指南

DeepSeekMine RAG实战:企业文档管理的百问测试与深度避坑指南 当我把公司整个项目的需求文档、设计稿、会议记录和代码注释全部导入DeepSeekMine时,原本以为这只是个简单的知识库搭建过程。但在一周内连续提出100多个专业问题后,这套系统展现…...

MATLAB实战:5分钟搞定倒立摆LQR控制(附完整代码)

MATLAB实战:5分钟搞定倒立摆LQR控制(附完整代码) 倒立摆作为经典的控制系统教学案例,一直是学习自动控制的必经之路。但很多初学者在面对复杂的数学推导和代码实现时,往往感到无从下手。本文将带你用最短的时间&#x…...

视觉-语音-文本三模态同步流式处理,全链路延迟压至<15ms,这7个被忽略的CUDA Graph陷阱你踩过几个?

第一章:视觉-语音-文本三模态同步流式处理的实时性本质 2026奇点智能技术大会(https://ml-summit.org) 实时性在三模态流式系统中并非仅由端到端延迟定义,而是源于跨模态时序对齐、计算资源动态调度与感知语义边界识别三者的协同约束。视觉帧率&#x…...

汉字的文化内涵与独特魅力

汉字的文化内涵与独特魅力汉字的精准性与高级性汉字被公认为世界上最精准、最高级的文字之一,其独特的造字逻辑与文化承载,使得许多汉字在英语中难以找到完全对应的翻译,这种“无解”的文化错位现象,在汉语中十分常见。例如&#…...

FPGA驱动ADS1256实现高精度数据采集系统设计

1. 为什么选择FPGA驱动ADS1256? 在工业测量和医疗设备领域,对模拟信号采集的精度要求往往达到微伏级别。传统的MCU方案在处理24位高精度ADC时常常力不从心,这时候FPGA的优势就凸显出来了。我去年参与过一个ECG医疗设备项目,最初尝…...

别再被TI官方原理图坑了!TPS65130/31关闭省电模式(PSP/PSN)的实战避坑指南

TPS65130/31设计实战:关闭省电模式的工程决策与热管理优化 当光电检测设备遭遇运放阵列供电异常时,示波器上跳动的纹波曲线往往暗示着更深层的电源架构问题。在最近一个医疗内窥镜成像模块的开发中,我们的团队遇到了与TI的TPS6513x系列芯片相…...

【Antd+Vue】优化Select组件大数据渲染性能的实战技巧

1. 为什么Select组件会卡顿? 当你在Vue项目中使用Ant Design Vue的Select组件渲染上千条数据时,可能会遇到明显的卡顿现象。这主要是因为浏览器需要一次性处理大量DOM节点,导致渲染性能下降。想象一下,你同时打开100个网页标签页和…...

避坑指南:ABAP调用CO_XT_COMPONENT_ADD为工单批量添加组件,这些细节不注意会报错

ABAP工单组件批量维护实战:CO_XT_COMPONENT_ADD深度避坑指南 在SAP生产订单管理系统中,批量维护工单组件是每个ABAP开发者都会遇到的高频需求。当标准BAPI无法满足复杂场景时,CO_XT_COMPONENT_ADD这类底层函数往往成为救命稻草——但稍有不慎…...

如何在机器人控制中应用惯性系与固连系转换?5个实际案例解析

如何在机器人控制中应用惯性系与固连系转换?5个实际案例解析 当机械臂在工厂流水线上精准抓取零件,或是无人机在复杂环境中自主避障时,其核心控制系统都在不断进行着一种"空间思维体操"——坐标系转换。这种在惯性系(世…...