news 2026/10/18 6:05:19

page_alloc free_reserved_area

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
page_alloc free_reserved_area

free_reserved_area()是内核启动后期用于将保留内存(reserved memory)释放回伙伴系统的核心函数。它通常服务于free_initmem()、free_initrd_mem()等场景,把初始化代码段、initrd 等不再需要的物理内存归还给分配器。

核心作用与设计意图

它的设计目标很明确:将一段物理地址范围内的“保留页”标记为可分配,并归还给伙伴系统。这些页在启动早期被memblock标记为保留,不参与常规分配;当相关用途(如内核初始化、initrd 挂载)结束后,通过这个函数将它们“解禁”。

参数解析

根据内核源码注释,函数的语义如下:

/* * Free reserved pages within range [PAGE_ALIGN(start), end & PAGE_MASK) * into the buddy system. The freed pages will be poisoned with pattern * "poison" if it's within range [0, UCHAR_MAX]. * Return pages freed into the buddy system. */ unsigned long free_reserved_area(void *start, void *end, int poison, const char *s)
参数含义
start起始地址(会被向上对齐到页边界)
end结束地址(会被向下对齐到页边界)
poison毒化填充值:在[0, UCHAR_MAX]范围内时,用该值填充每页;否则不毒化
s描述字符串,用于打印日志(如"unused kernel")

返回值:释放到伙伴系统的页数。

核心逻辑

1. 地址对齐

start = (void *)PAGE_ALIGN((unsigned long)start); end = (void *)((unsigned long)end & PAGE_MASK);

将start向上对齐、end向下对齐,确保操作以页为单位。

2. 遍历释放每一页

for (pos = start; pos < end; pos += PAGE_SIZE, pages++) { struct page *page = virt_to_page(pos); void *direct_map_addr; direct_map_addr = page_address(page); if ((unsigned int)poison <= 0xFF) memset(direct_map_addr, poison, PAGE_SIZE); free_reserved_page(page); }

这里有一个重要的历史修复:早期代码直接对pos做memset(),但如果pos是内核镜像的别名映射(alias mapping)且落在只读区域,memset会失败。修复后改为先通过page_address(page)获取直接映射地址,再对该地址毒化,确保总是可写的。

3. 打印日志

if (pages && s) pr_info("Freeing %s memory: %ldK\n", s, pages << (PAGE_SHIFT - 10));

释放成功后,打印释放的内存大小(KB)。

典型调用场景

1. 释放内核初始化代码段

// include/linux/mm.h static inline unsigned long free_initmem_default(int poison) { extern char __init_begin[], __init_end[]; return free_reserved_area(&__init_begin, &__init_end, poison, "unused kernel"); }

内核启动完成后,__init段(标记为__init的函数和数据)不再需要,通过这个函数释放回伙伴系统。

2. 释放 initrd 内存

// arch/powerpc/mm/mem.c void __init free_initrd_mem(unsigned long start, unsigned long end) { free_reserved_area((void *)start, (void *)end, -1, "initrd"); }

initrd 内容被解压/挂载后,其占用的内存被释放。注意poison = -1表示不毒化(因为-1不在[0, 255]范围内)。

3. 毒化模式选择

  • poison = 0:用 0 填充,用于某些需要清零的场景。

  • poison = -1:不毒化,直接释放。

  • 具体毒化值(如POISON_FREE_INITMEM)由平台定义。

历史演进

  • 2013 年:Jiang Liu 的补丁增强了free_reserved_area(),使其支持用 0 毒化内存,并修复了 s390 上 initmem 毒化被误禁的问题。

  • 2018 年:补丁修复了“非直接映射地址”调用失败的问题,通过page_address()获取可写别名。

  • 2026 年:重构提案将free_reserved_area()从page_alloc.c移至memblock.c,并与memblock_free_late()合并共性逻辑。

总结

free_reserved_area()是保留内存的释放阀门:它将[start, end)范围内按页对齐的保留页逐页毒化(可选)并通过free_reserved_page()归还伙伴系统,返回释放的页数。它服务于free_initmem()(释放内核初始化段)、free_initrd_mem()(释放 initrd)等启动后期清理场景,是内核把“启动专用内存”转化为“通用可分配内存”的关键一步。

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

Matlab自动驾驶决策规划控制实战:从状态机到纯跟踪完整代码解析

自动驾驶决策规划控制Matlab代码实战&#xff0c;听起来又长又劝退&#xff0c;但我实际跑通之后发现&#xff0c;这其实是进入自动驾驶领域性价比最高的一条路。最近不少朋友来问我怎么入门&#xff0c;我的建议是别一上来就啃C、Linux那一套&#xff0c;先用Matlab把决策、规…

作者头像 李华
网站建设 2026/10/18 6:02:49

Playwright Trace Viewer:自动化测试的完整证据链

前两天帮一位校招阶段的朋友复盘自动化测试项目&#xff0c;代码写得挺干净&#xff0c;断言也覆盖了核心路径&#xff0c;但面试的时候被问住了一句话&#xff1a;跑挂了之后&#xff0c;你怎么证明不是环境问题&#xff1f;他想了想说&#xff0c;有截图。截图当然有&#xf…

作者头像 李华
网站建设 2026/10/18 6:02:17

大O表示法面试全攻略:从复杂度分析到数据结构性能优化

1. 为什么面试官总爱问大O表示法我在做技术面试官的时候&#xff0c;几乎每场技术面都会问候选人关于算法复杂度的问题。倒不是故意刁难&#xff0c;而是这一题能非常高效地把候选人的基础功底测出来。你想想&#xff0c;一个写了两三年业务代码的人&#xff0c;天天增删改查&a…

作者头像 李华
网站建设 2026/10/18 6:02:07

基于YOLOv5的钢轨缺陷检测:VOC转YOLO与训练避坑全流程

简介&#xff1a;基于YOLOv5的钢轨缺陷检测项目&#xff0c;面向铁路设施维护人员及计算机视觉学习者&#xff0c;目标是通过深度学习实现对钢轨裂纹、磨损、剥离等表面缺陷的自动定位与分类&#xff0c;提升巡检效率与安全性。该资源压缩包共2000个文件&#xff0c;其中1994个…

作者头像 李华
网站建设 2026/10/18 6:01:31

AI文档预处理:为什么Markdown化是提升大模型准确率的关键一步

1. 为什么“直接丢文件给AI”正在悄悄拖垮你的效率你有没有过这种经历&#xff1a;把一份20页的PDF产品说明书拖进对话框&#xff0c;等了半分钟&#xff0c;AI只回了一句“已收到”&#xff0c;再问具体问题&#xff0c;它却开始胡说八道&#xff1f;或者把Excel表格截图扔过去…

作者头像 李华
网站建设 2026/10/18 5:57:53

AI全链路问卷工具PaperXie:从无效问卷到可靠数据的完整指南

做问卷的人最怕什么&#xff1f;我猜不是发不出去&#xff0c;而是辛辛苦苦改了三遍题目&#xff0c;回收了几百份数据&#xff0c;一交叉分析&#xff0c;全是废话。问性别和满意度没关系&#xff0c;问收入和购买意愿不相关&#xff0c;维度之间互相打架&#xff0c;信度算出…

作者头像 李华