内存管理-80-PAGE_REPORTING-6.1
一、page report 简介
CONFIG_PAGE_REPORTING —— 空闲页报告机制
1. 一句话总结
Page Reporting 让虚拟机(Guest)告诉宿主机(Host)"哪些物理页我不用了",Host 可以回收这些页面的物理内存给其他虚拟机或自身使用,实现内存超分(overcommit)。
2. 存在意义
在虚拟化环境中:
┌──────────────── Host ────────────────────────┐
│ │
│ 物理内存 64GB │
│ │
│ ┌─── VM1 ───┐ ┌─── VM2 ───┐ ┌── VM3 ──┐ │
│ │ 分配 16GB │ │ 分配 16GB │ │分配 16GB│ │
│ │ 实际用 8GB │ │ 实际用 12GB│ │实际用 4GB│ │
│ │ 空闲 8GB ↓ │ │ 空闲 4GB │ │空闲 12GB │ │
│ └───────────┘ └───────────┘ └─────────┘ │
│ │
│ 问题:VM1 和 VM3 空闲的 20GB,Host 不知道! │
│ Host 认为 48GB 都被使用了,无法分给新 VM │
└──────────────────────────────────────────────┘
没有 Page Reporting 时: Guest 释放了内存(free 回 buddy),但 Host 不知道。Host 的 hypervisor 仍为这些页面保留物理内存映射。
有 Page Reporting 时: Guest 释放页面后主动告诉 Host "这些页面我不用了",Host 可以:
(1) 解除这些页面的物理内存映射(释放 Host 的 RAM);
(2) 将这些 RAM 分配给其他 VM 或 Host 进程;
(3) 当 Guest 再次访问这些页面时,Host 按需重新分配(zero-fill fault);
3. 工作原理
3.1 Guest 内核:
__free_one_page(page, ...) 释放页面到 buddy └── page_reporting_notify_free(order) <-- 通知 reporting 子系统 └── 标记有新的空闲高阶页面可报告 page_reporting_process() 后台工作: ├── 扫描 buddy free_list 中 >= 阈值 order 的页面 ├── 将这些页面从 free_list 临时取出 ├── 组成一个 scatter-gather list ├── 调用 report 回调 --> virtio-balloon / 其他 backend │ └── 告诉 Host "这些 GPA(Guest Physical Address) 页面我不用了" ├── Host 处理(解除映射/标记为可回收) └── 将页面放回 buddy free_list(标记为 "reported")
3.2 与 Balloon 的区别
--------------------------------------------------------------------------------------------------- 特性 Balloon(virtio-balloon) Page Reporting --------------------------------------------------------------------------------------------------- 方向 Host 要求 Guest 交还内存 Guest 主动告知空闲页 Guest 开销 需要实际"充气"占用 Guest 内存 无开销,只报告 buddy 上本就空闲的页面 恢复速度 需要"放气"操作 Guest 重新分配时自动触发 page fault 粒度 逐页控制 批量报告高阶空闲块 适用场景 动态调整 VM 内存大小 透明地回收 Guest 不用的内存 对 Guest 的侵入 有(实际减少 Guest 可用内存) 无(只报告已经空闲的) ---------------------------------------------------------------------------------------------------
4. 核心代码路径
4.1 通知入口(__free_one_page 末尾)
//mm/page_alloc.c — __free_one_page done_merging: add_to_free_list(page, zone, order, migratetype); /* 通知 page reporting:有新的空闲高阶页面 */ if (!(fpi_flags & FPI_SKIP_REPORT_NOTIFY)) page_reporting_notify_free(order);
4.2 通知实现
//mm/page_reporting.c void page_reporting_notify_free(unsigned int order) { /* 只报告 >= 阈值 order 的页面(默认 pageblock_order,避免报告碎片), 实测是 11,恒关闭的 */ if (order >= page_reporting_order) schedule_delayed_work(&reporting_work, ...); }
4.3 报告工作函数
static void page_reporting_process(struct work_struct *work) { for_each_populated_zone(zone) { for (order = page_reporting_order; order < MAX_ORDER; order++) { for (mt = 0; mt < MIGRATE_TYPES; mt++) { /* 从 free_list 取出未报告的页面 */ page = get_unreported_pages(zone, order, mt); /* 组成 scatterlist 批量报告 */ sg_set_page(&sgl[i], page, PAGE_SIZE << order, 0); } } /* 调用后端驱动的 report 回调 */ reporting_dev->report(reporting_dev, sgl, nents); /* 将页面标记为 "reported" 后放回 free_list */ put_reported_pages(zone, sgl, nents); } }
4.4 后端注册(virtio-balloon 为例)
//drivers/virtio/virtio_balloon.c static int virtballoon_free_page_report(struct page_reporting_dev_info *prdev, struct scatterlist *sg, unsigned int nents) { /* 通过 virtio 队列告诉 Host 这些 Guest Physical Addresses 空闲了 */ virtqueue_add_inbuf(vq, sg, nents, ...); virtqueue_kick(vq); /* Host 收到后可以解除这些 GPA 对应的 HPA 映射 */ wait_for_host_ack(); return 0; } /* 注册 */ page_reporting_register(&vb->pr_dev_info);
5. 如何使用
5.1 在 Guest 内核中开启
CONFIG_PAGE_REPORTING=y
这是一个框架,本身不做任何事。需要后端驱动注册 report 回调。
5.2 后端驱动
(1) virtio-balloon(QEMU/KVM 环境):CONFIG_VIRTIO_BALLOON=y + QEMU 开启 free-page-reporting=on;
(2) Hyper-V balloon:Windows Host 环境;
(3) 自定义后端:任何驱动都可以调用 page_reporting_register() 注册;
5.3 QEMU 启动参数示例
qemu-system-aarch64 ... \ -device virtio-balloon-pci,free-page-reporting=on Guest 内核中的调优: # 查看/修改最小报告 order(默认 = pageblock_order = 9 或 10), 只有 >= 这个 order 的空闲块才会被报告 cat /sys/kernel/mm/page_reporting/page_reporting_order # 大 order 报告更高效(一次报告 2MB),但小 order 可以回收更多碎片内存.
6. 总结
---------------------------------------------------------------------------------------------- 维度 说明 ---------------------------------------------------------------------------------------------- 功能 Guest 向 Host 报告空闲物理页面 目标 让 Host 回收 Guest 不用的内存,实现内存超分 适用环境 虚拟化(KVM/QEMU、Hyper-V 等) 裸机上 无效果(无后端注册时零开销) 后端 virtio-balloon、hv-balloon 等 报告阈值 只报告高阶空闲块(>= pageblock_order),避免碎片页面的低效报告 ----------------------------------------------------------------------------------------------
对 Guest 的影响 透明——页面仍在 buddy free_list 上,Guest 可以随时再分配
二、功能只是 Linux Guest + Linux Hypervisor 才能使用吗
1. 概述
Page Reporting 不限定 Hypervisor 类型。框架本身是 Linux Guest 内核内部的通用机制,不关心 Hypervisor 是 Linux/QNX/Nebula 还是其他任何东西。
但它需要一个后端驱动把空闲页信息传递给 Hypervisor。目前 Linux 主线内核中只有 virtio-balloon 和 hv_balloon 两个后端——这两个分别对接 KVM/QEMU 和 Hyper-V 的协议。
2. QNX / Nebula(闭源)能否使用
取决于 Hypervisor 侧是否提供了接收空闲页通知的接口。
--------------------------------------------------------------------------------------------------------------------------------- 情况 能否使用 --------------------------------------------------------------------------------------------------------------------------------- Nebula 实现了 virtio-balloon 设备(带 free-page-reporting 特性) ✅ 直接可用,Linux Guest 的 virtio-balloon 驱动自动对接 Nebula 有自定义的 hypercall/共享内存通道但没有 virtio-balloon 需要编写自定义后端驱动注册到 page_reporting 框架 Nebula 完全没有提供此类接口 ❌ 无法使用 ---------------------------------------------------------------------------------------------------------------------------------
闭源本身不是障碍——Page Reporting 的后端驱动运行在 Linux Guest 内核中(开源侧),只要知道 Hypervisor 的通信协议(hypercall 号、共享内存地址、消息格式)就能编写驱动。关键是 Hypervisor 侧必须有能力接收通知并做出"回收物理页"的动作。
从内核源码中 Nebula 相关模块(virtio_vsock、virtio_blk、virtio_net 等)来看,Nebula 确实实现了 virtio 设备框架。如果它也实现了 virtio-balloon 设备并支持 VIRTIO_BALLOON_F_FREE_PAGE_HINT 特性位,那 Page Reporting 就能开箱即用。建议直接在 Guest 中检查:
# 有没有 virtio-balloon 设备--实测两个都没有 ls /sys/bus/virtio/devices/ | grep balloon # 或 dmesg | grep -i balloon
posted on 2026-08-24 11:41 Hello-World3 阅读(6) 评论(0) 收藏 举报
浙公网安备 33010602011771号