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

linux内存迁移

Linux 内存迁移(Page Migration)是内核在进程虚拟地址完全不变的前提下,将物理页面从一个地址透明搬运到另一个地址的核心机制。它是CMA、内存规整(Compaction)、NUMA 优化、内存热插拔的基础。

内存迁移定义

虚拟地址 → 物理页的映射被修改,数据被拷贝到新物理页,旧页释放。进程完全无感知

核心用途

  1. CMA 连续内存分配(你最关心):回收被占用的 CMA 页,腾出大块连续物理内存。
  2. 内存规整(Compaction):解决外部碎片,满足高阶页(order>3)、巨页(HugeTLB)分配。
  3. NUMA 节点迁移:把页移到本地节点,降低访存延迟。
  4. 内存热插拔:下线物理内存前迁移走所有页。
  5. 硬件场景:GPU / 设备内存、TEE 安全内存、保留区复用。

核心原理与流程

页面迁移不改变进程虚拟地址,仅调整物理页归属,关键路径在mm/migrate.c,核心步骤如下:

  1. 隔离页面:通过folio_isolate_lru()从 LRU 链表移除目标页,递增引用计数(refcount),防止迁移中被释放。
  2. 锁定与同步:锁定旧页与新页,确保写回(writeback)完成,避免数据不一致。
  3. 页表转换:将旧页所有页表项转为迁移条目(migration entry),此时访问者会阻塞等待;若 mapcount 非零则放弃迁移。
  4. 内容迁移:拷贝旧页内容到新页,更新页表指向新页,释放旧页。
  5. 恢复与统计:解锁页面,更新页框计数器,更新迁移成功 / 失败统计。

不可迁移页面

  • 内核态不可移动页(MIGRATE_UNMOVABLE),如固定映射的内核内存;
  • 共享页需CAP_SYS_NICE权限,否则跳过;
  • 正在写回(writeback)或有外部引用的页。

页面可迁移性(MIGRATE_TYPES)

内核按能否迁移把页分成 4 类(mm/page_alloc.c):

类型含义能否迁移典型页面
MIGRATE_MOVABLE完全可迁移✅ 是用户页、页缓存、CMA 临时占用页
MIGRATE_RECLAIMABLE可回收(非迁移)❌ 否slab 页(可回收释放)
MIGRATE_UNMOVABLE不可迁移❌ 绝对否内核常驻、内核栈、固定映射页、部分驱动页
MIGRATE_CMACMA 专用(可迁移)✅ 是CMA 区域页(空闲时借给 MOVABLE)
MIGRATE_ISOLATE隔离态(迁移中)被隔离、暂不分配

CMA 关键:CMA 区域页默认是MIGRATE_CMA,空闲时允许MIGRATE_MOVABLE借用;当驱动要分配时,内核把这些被借用页迁移出去,恢复连续。

完整迁移流程(内核态)

核心文件:mm/migrate.c入口:migrate_pages()/alloc_contig_range()(CMA 用)

1. 页面隔离(Isolate)

  • 把目标页从 LRU 摘下 →isolate_lru_page()
  • 页引用计数 +1,防止释放
  • 标记为MIGRATE_ISOLATE,禁止新分配

2. 锁定与检查

  • 锁页(lock_page()),确保无写回、无并发访问
  • 检查:是否正在写回、是否有永久引用、是否不可迁移

3. 分配新页

  • 按旧页属性(order、migratetype、nid)分配新物理页
  • CMA 场景:新页从非 CMA 区域 MOVABLE分配

4. 页表冻结(Migration Entry)

  • 把所有 PTE 替换为特殊迁移条目(swap entry-like)
  • 访问会阻塞直到迁移完成 → 保证原子性

5. 数据拷贝 & 元数据迁移

  • migrate_page_copy():拷贝内容、PG 标志、引用计数
  • migrate_page_move_mapping():更新 address_space、radix tree、匿名页映射

6. 页表修复 & 解锁

  • 用新页 PFN 替换迁移条目,刷新 TLB
  • 解锁、释放旧页引用
  • 旧页放回伙伴系统(CMA 页回到 CMA 池)

7. 失败回滚

  • 迁移失败:恢复旧页映射、解除隔离、放回 LRU

CMA 内存迁移

CMA 分配连续内存的唯一核心动作就是迁移

CMA 分配流程(含迁移)

  1. cma_alloc()申请 N 个连续页
  2. alloc_contig_range()核心:
    • start_isolate_page_range():把目标范围设为MIGRATE_ISOLATE
    • __alloc_contig_migrate_range()迁移所有被占用页
    • 范围全部空闲后,从 buddy 系统摘除
  3. 迁移成功 → 返回连续物理页;失败 → 重试 / 报错

CMA 迁移特点

  • 只迁移 MOVABLE/CMA 页
  • 不可迁移页存在 → CMA 分配直接失败(最常见坑)
  • 迁移对驱动完全透明dma_alloc_coherent()自动走 CMA

三种迁移模式(enum migrate_mode)

// include/linux/migrate.h enum migrate_mode { MIGRATE_ASYNC, // 异步,不阻塞、不回收、快速失败(规整用) MIGRATE_SYNC_LIGHT,// 同步,轻度阻塞,不回收脏页 MIGRATE_SYNC, // 完全同步(CMA/热插拔用):阻塞、回收、必成功 };
  • CMA 强制用 MIGRATE_SYNC:必须确保迁移成功,才能腾出连续内存

内核 API(驱动 / 模块可用)

1. 通用页面迁移

// 迁移一页 int migrate_page(struct address_space *mapping, struct page *newpage, struct page *page, enum migrate_mode mode); // 迁移一页(folio 新版接口) int migrate_folio(struct address_space *mapping, struct folio *dst, struct folio *src, enum migrate_mode mode); // 批量迁移页链表 int migrate_pages(struct list_head *source, new_folio_t new, free_folio_t free, unsigned long private, enum migrate_mode mode, int reason, unsigned int *ret_succeeded);

2. CMA 专用(分配连续内存)

// 从 CMA 池分配连续页(会触发迁移) struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align, bool no_warn); // 释放回 CMA void cma_release(struct cma *cma, struct page *pages, size_t count);

3. 保留内存映射(no-map 静态区)

// 静态 reserved-memory(no-map)需手动映射 void *vaddr = memremap(phys_addr, size, MEMREMAP_WC); memunmap(vaddr);

用户态接口 & 工具

1. 系统调用

  • mbind()+MF_MOVE/MF_MOVE_ALL:迁移进程内存到指定 NUMA 节点
  • migrate_pages():跨进程迁移
  • move_pages():单页迁移

2. 命令行工具

# 迁移进程页到 NUMA 节点 migratepages <PID> <from-node> <to-node> # 查看迁移状态 cat /proc/vmstat | grep pgmigrate # pgmigrate_success 成功数 # pgmigrate_fail 失败数 # 查看 CMA cat /proc/meminfo | grep Cma cat /sys/kernel/debug/cma/cma_0/used # 查看页迁移类型(debug) cat /sys/kernel/debug/page_owner

Reserved Memory / 静态 / 动态 / CMA 迁移对比

类型能否迁移迁移触发用途
静态 reserved(no-map)❌ 绝对不可从不硬件固定地址、安全区、固件
动态 reserved(no-map)❌ 不可从不驱动私有、非共享内存
CMA(reusable)完全可迁移cma_alloc/alloc_contig_range大块连续 DMA、GPU/VPU/ 网卡
普通用户页✅ 可迁移规整、NUMA、CMA 回收应用内存、页缓存

性能与风险控制

  1. 性能开销
    • 迁移涉及页表修改、内存拷贝与 TLB 失效,高并发场景可能引入抖动;
    • 建议在业务低峰期执行,避免影响延迟敏感业务。
  2. 失败排查
    • 检查PGMIGRATE_FAIL计数器(/proc/vmstat);
    • 确认目标节点有足够空闲内存(free -m);
    • 验证权限(CAP_SYS_NICE)与页面可迁移性(numa_maps)。
  3. 内存规整(Compaction)
    • 目的:合并碎片生成高阶连续页(如大页),依赖迁移;
    • 触发时机:高阶分配失败、手动触发、后台kcompactd定期执行;
    • 监控:/proc/buddyinfo查看高阶页数量,/proc/pagetypeinfo查看迁移类型分布。

扩展场景

  1. 设备内存迁移:GPU SVM 等场景通过migrate_vma_*/migrate_device_*API,将页在主机内存与设备私有内存间迁移;
  2. 内存热插拔:依赖迁移实现节点上线 / 下线时的页重定位。

总结

Linux 内存迁移是 NUMA 优化、碎片整理的核心机制,核心依赖migrate_pages系统调用与numactl工具。实践中需关注权限内存可用性性能开销,结合numastatnuma_maps等工具定位问题。若需细粒度控制,可使用move_pages单页接口;若需整理碎片,手动触发compact_memory即可。

http://www.jsqmd.com/news/638738/

相关文章:

  • 亲测有效!Z-Image-Turbo解决AI绘画三大痛点:慢、黑、崩
  • 盘点2026年河南亲子海盗船厂,口碑好的品牌大揭秘 - 工业品牌热点
  • 别再只会用Cesium加载地球了!手把手教你用Cesium Ion和3D Tiles打造一个智慧城市可视化大屏(附完整代码)
  • 2026年靠谱的移民企业推荐,诚信专业机构助你开启海外新生活 - mypinpai
  • 还在为20V/36V工具12V供电方案续航差、纹波大、发热重发愁吗?CSM7343F12SR拥有45V高耐压,3μA极致微功耗让工具待机续航翻倍,让你的电动工具设计更稳、更省、更简单
  • 告别提取码焦虑:3分钟解锁百度网盘资源的智能助手
  • 2026 四款 AI 企业部署指南
  • 006、技能重构(下):Python开发者必须掌握的AI工具链与硬核技能
  • 【Java】报错:NullPointerException
  • Qwen2.5-VL-7B-Instruct开发者指南:自定义提示词模板+视觉指令工程最佳实践
  • 云原生数据治理最佳实践
  • Matlab MK突变检验算法程序详解:含测试数据集与注释,初学者适用,数据替换即可快速生成图表
  • iFluor 750-beta-Amyloid (1-42)红外荧光探针 蛋白聚集可视化工具
  • 规划建议:为产品经理量身定制的CAIE认证备考节奏与时间管理方案
  • 如何解决游戏按键冲突:Hitboxer终极按键映射工具指南
  • 从 Seq2Seq 到注意力:用「翻译一句话」搞懂编码器、解码器与 Query/Key/Value
  • 三步解锁WeMod Pro:免费获取高级功能的终极指南
  • Wan2.2-I2V-A14B在C语言项目中的调用:通过封装Python服务实现
  • BarrageGrab:多平台直播弹幕实时采集的一体化解决方案
  • AIVideo效果展示:多风格视频生成作品,实测惊艳
  • CefFlashBrowser:Flash内容终极解决方案,让经典重现的专业工具
  • STM32H7 GPIO实战:用CubeMX和STM32CubeProgrammer实现LED闪烁(避坑指南)
  • 李慕婉-仙逆-造相Z-Turbo网络应用:解决复杂网络拓扑图自动绘制
  • 【PyTorch】单机多卡数据并行实战:从DataParallel到性能优化
  • 如何在5分钟内免费配置你的Windows本地实时语音转文字工具
  • Pixel Couplet Gen惊艳案例:用户输入‘升职加薪’生成带像素金币动画的春联
  • PVE Tools技术深度解析:Proxmox VE自动化管理工具的价值实现与架构设计
  • 做宜选影票特惠电影票项目要配齐这些系统开发注意事项真的很多快来看!
  • 深耕育苗基质赛道 铸就国内知名农业基质品牌
  • 实战分享:Fun-ASR流式语音识别在在线教育场景的应用