news 2026/10/20 18:53:12

page_alloc __rmqueue_smallest

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
page_alloc __rmqueue_smallest

__rmqueue_smallest()是伙伴系统分配路径的核心函数,负责从指定迁移类型的空闲链表中,找到最接近请求阶数的页块并分配出去。

核心作用

它实现了伙伴系统"最小可用块"的分配策略:从请求的order开始,逐级向上查找第一个非空的空闲链表,取出页块,若块大于所需则拆分。这种策略尽量减少对大块的浪费,有利于保持内存连续性。

参数解析

参数含义
zone目标内存区域
order请求的分配阶数
migratetype迁移类型(决定从哪条链表分配)

核心流程

典型实现如下:

static __always_inline struct page *__rmqueue_smallest(struct zone *zone, unsigned int order, int migratetype) { unsigned int current_order; struct free_area *area; struct page *page; /* 从请求阶数开始,逐级向上查找 */ for (current_order = order; current_order < MAX_ORDER; ++current_order) { area = &zone->free_area[current_order]; /* 查看该阶数、该迁移类型是否有空闲块 */ page = get_page_from_free_area(area, migratetype); if (!page) continue; /* 找到了,从链表移除并拆分 */ page_del_and_expand(zone, page, order, current_order, migratetype); trace_mm_page_alloc_zone_locked(page, order, migratetype); return page; } return NULL; }

逐步说明

1. 从请求阶数开始向上查找

for (current_order = order; current_order < MAX_ORDER; ++current_order)
  • 先看请求的order是否有空闲块;

  • 没有就试order + 1,直到MAX_ORDER - 1。

  • 这保证优先使用最小的可用块,减少对大块的浪费。

2. 查看目标迁移类型的链表

area = &zone->free_area[current_order]; page = get_page_from_free_area(area, migratetype); if (!page) continue;
  • get_page_from_free_area():前面讲的,查看该链表首个页块(不摘除)。

  • 链表为空则试下一阶。

3. 从链表删除并拆分

page_del_and_expand(zone, page, order, current_order, migratetype);
  • page_del_and_expand():

    • __del_page_from_free_list()从链表摘除整个高阶块;

    • expand()拆分,多余部分归还低阶链表;

    • account_freepages()一次性更新统计。

  • 最终page指向恰好order阶的页块。

4. 返回页块

return page;
  • 返回分配到的页块首页;

  • 若遍历完所有阶都没找到,返回NULL。

在分配路径中的位置

它是__rmqueue()的首选分配路径:

__rmqueue(zone, order, migratetype, alloc_flags) ├── __rmqueue_smallest(zone, order, migratetype) // ← 首先尝试 │ └── 从同迁移类型链表中找最小可用块 └── if (!page) __rmqueue_fallback(zone, order, migratetype, ...) // 降级:从其他类型偷

关键设计点

1. 只操作指定迁移类型

  • 它只在migratetype对应的链表中查找。

  • 如果该类型没有空闲块,返回NULL,由__rmqueue_fallback()负责从其他类型"偷"页。

2. "Smallest" 的含义

  • 优先用最小的可用块,避免过度拆分大块。

  • 例如请求 order 3,如果有 order 3 空闲块就直接用;只有没有时才拆 order 4/5…。

3. 与__rmqueue_fallback()的分工

  • __rmqueue_smallest():同类型内查找;

  • __rmqueue_fallback():跨类型偷取。

4. 迁移类型 vs pageblock 迁移类型

  • 这里的migratetype是请求的迁移类型;

  • 分配后可能通过set_pageblock_migratetype()更新 pageblock 的实际类型。

总结

__rmqueue_smallest()是伙伴系统同类型分配的核心:它从请求阶数开始逐级向上扫描free_area,找到第一个非空的同迁移类型链表,用page_del_and_expand()取出并拆分出恰好所需的页块。它体现了"最小可用块"策略,尽量减少对大块的浪费;如果同类型无可用块,则交由__rmqueue_fallback()跨类型偷取。

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

作业一难就放弃?把「扛得住的心韧力」做成训练闭环

技术向 / 干货。面向想用「系统」替代「反复讲道理」的家长与开发者。 作者&#xff1a;学心教研 0. 结论先行 面对孩子在书桌前「一遇到难题就退缩发脾气」&#xff0c;很多家长习惯用「坚持就是胜利」「再动动脑子」这类道理去施压。但从认知神经机制来看&#xff0c;孩子一难…

作者头像 李华
网站建设 2026/10/16 2:10:35

影石系统组 一二面OC面经

一面1. 封装、继承、多态分别是什么&#xff1f;什么是封装&#xff1f;继承有哪些继承方式&#xff1f;封装&#xff1a;将属性和方法封装到类中&#xff0c;隐藏内部实现细节&#xff0c;对外提供访问接口&#xff0c;保护数据。继承&#xff1a;子类复用父类的成员&#xff…

作者头像 李华
网站建设 2026/10/20 18:52:22

低温温度计标定:LabVIEW 怎么把它做在线

低温温度计的标定&#xff0c;通常是一支一支手工做&#xff1a;恒温、等稳定、记数、换点&#xff0c;一轮下来几周。有人把这件事交给了 LabVIEW&#xff0c;做了在线自动标定——4.2 到 25 K 这段&#xff0c;控温精度优于 4 mK&#xff0c;而且人不用守在旁边。01 这套系统…

作者头像 李华
网站建设 2026/10/16 7:46:30

VS Code录屏新神器!终不用于第三方录键工具了

不知道你有没有过这样一段 尴尬往事。 早年打算录一期编程教学视频,兴致勃勃打开录屏软件,刚准备上手演示。突然意识到一个很现实的难题:屏幕前的观众根本看不到你按下了什么快捷键。 你手指飞快敲下Ctrl+B收起侧边栏,视频里面画面一闪就完事。看回放的小伙伴一脸茫然:哎…

作者头像 李华
网站建设 2026/10/14 5:48:10

基于SpringBoot的餐饮财务管理系统实战:从架构到部署

做餐饮财务管理系统这件事&#xff0c;我太有发言权了。尤其当项目名落到"基于SpringBoot的餐饮财务管理系统_ui41jy6y_hxj023"这种带编号的工程上&#xff0c;十有八九是课程设计、毕业设计或者小团队内部要快速落地的项目。SpringBoot这个关键词&#xff0c;最近在…

作者头像 李华