找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2262

积分

0

好友

318

主题
发表于 前天 03:45 | 查看: 8| 回复: 0

在审查涉及复合页面的补丁时,编辑发现对这部分知识理解不足。通过深入源码查证,认为有必要分享关于Linux内核中复合页面的知识。对于所有希望深入理解这一概念的读者,这里提供一份快速指南。

复合页面实质上是将两个或多个物理连续的页面组合成一个单元,在许多方面可被视为单个更大的页面。它们最常用于创建大页(huge pages),应用于hugetlbfs或透明大页子系统,但也会出现在其他场景中。复合页面可作为匿名内存使用,或作为内存管理中的缓冲区;然而,它们不能出现在页缓存(page cache)中,因为页缓存仅支持单页(singleton pages)。

分配复合页面只需调用常规内存分配函数(如 alloc_pages()),并设置 __GFP_COMP 分配标志且阶数(order)至少为1。由于复合页面的实现方式,无法创建阶数为零(单页)的复合页面。(分配的“阶数”是要分配的页面数以2为底的对数;因此,0对应单页,1对应两页,以此类推。)

需注意,复合页面与常规高阶分配请求返回的页面不同。例如:

pages = alloc_pages(GFP_KERNEL, 2);  /* 未设置__GFP_COMP */

将返回四个物理连续的页面,但它们不会构成复合页面。区别在于创建复合页面涉及生成大量元数据;而多数情况下这些元数据并不需要,因此可以避免创建开销。

那么这些元数据具体是什么样的呢?由于大部分元数据存储在关联的 page 结构体中,可以想象其复杂性。让我们先从页面标志开始。复合页面中的第一个(普通)页面称为“头页”,它设置了 PG_head 标志。所有其他页面称为“尾页”,它们带有 PG_tail 标志。至少,在页面标志充足的系统(即64位系统)上是这样处理的。在32位系统中,由于没有多余的页面标志可用,采用不同的方案:复合页面中的所有页面都设置 PG_compound 标志,尾页额外设置 PG_reclaim 标志。PG_reclaim 位通常由页缓存代码使用,但由于复合页面不能出现在页缓存中,该标志可在此处重用。

不过,处理复合页面的代码无需担心不同的标记约定。无论使用哪种约定,只要传入的页面是复合页面,调用 PageCompound() 将返回真值。若有必要区分头页和尾页,可使用 PageHead()PageTail()

每个尾页的 struct page 中都有一个指向头页的指针,存储在 first_page 字段。该字段与 private 字段、页面持有页表项时使用的自旋锁或页面由slab分配器管理时使用的 slab_cache 指针共享存储空间。可使用 compound_head() 辅助函数查找与任何尾页关联的头页。

还有一些描述整个复合页面的信息:页面的阶数(大小)以及当页面不再需要时用于将其返还系统的析构函数。人们可能会首先想到将这些信息存储在头页的 struct page 中,但那里没有空间。实际上,阶数存储在第一尾页的 page 结构的 lru.prev 字段中。尽管 struct page 中许多重叠字段使用了联合体(union),但这里阶数是直接转换为指针类型后存储在指针字段中的。类似地,析构函数的指针存储在第一尾页 struct pagelru.next 字段中。这种将复合页面元数据扩展到第二页结构的做法,解释了为什么复合页面必须至少由两页组成。

顺便提一下,内核中只声明了两个复合页面析构函数。默认情况下使用 free_compound_page(),它所做的只是将内存返还给页面分配器。而hugetlbfs子系统使用 free_huge_page() 以保持其计数的更新。

在大多数情况下,复合页面并非必需,可使用普通分配;调用代码需要记住它分配了多少页面,但除此之外,复合页面中存储的元数据并不需要。然而,每当需要将一组页面视为整体处理(即使有人引用其中的单个页面)时,复合页面就显得尤为重要。透明大页就是一个经典例子:如果用户空间尝试更改大页某部分的保护权限,则需要定位整个大页并将其拆分。各种驱动程序也使用复合页面来简化对大缓冲区的管理。

以上基本涵盖了复合页面与普通高阶分配的所有区别。大多数开发人员在内核工作中不会遇到复合页面。但在确实需要将一组页面视为单个单元处理的情况下,复合页面很可能成为解决方案工具包的一部分。更多关于内核和内存管理的讨论,欢迎访问云栈社区进行交流。

来源:https://lwn.net/Articles/619514/




上一篇:Visual Studio Code 1.108正式发布:终端GPU加速、Git忽略空格与AI代理技能升级
下一篇:开源 SpringBoot3 轻量级、组件化 Web 框架:模块化构建专属架构
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-14 15:40 , Processed in 0.212578 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表