1. 概述
页面迁移(page migrate)最早是为 numa 系统提供一种将进程页面迁移到指定内存节点的能力用来提升访问性能。后来在内核中广泛被使用,如内存规整、cma、内存hotplug等。
页面迁移对上层应用业务来说是不可感知的,因为其迁移的是物理页面,而应用只访问的是虚拟内存。内核迁移完成后,更新修改对应页表指向迁移后的页面即可。当然了这里说的不可感知是指业务不太关注,也不需要做对应修改。实际上有些场景发生页面迁移是业务性能是有影响的,下面会详细描述。
2. 典型场景
我们列举2个内核中发生页面迁移的典型场景。
2.1 numa balancing引起的页面迁移
在典型 numa 中,存在多个 node, 本地 cpu 访问本地 node 节点对应的 memory 性能会快一些。
linux 的 numa 自动均衡机制会尝试将内存迁移到正在访问它的 cpu 节点所在的 node。如下图所示, cpu24 ~ cpu47 访问不是本地 node 对应的 memory,性能会比较慢,系统会将其迁移到本地 node 对应的 memory 以提升访问性能。
迁移后如下图:
2.2 内存碎片整理
系统使用一段时候后,由于内存碎片的原因,较难满足连续内存需求,如果需要分配连续大块内存,需要进行内存规整以形成大块连续内存,页面迁移是内存碎片整理的基础。
3. 实现分析
3.1 迁移模式
内核中通过接口 migrate_pages 实现页而迁移, 分为3个模式。
模式 简介 应用场景
migrate_async 异步迁移,过程中不会发生阻塞 内存分配slowpath
migrate_sync_light 轻度同步迁移,允许大部分的阻塞操作,唯独不允许脏页的回写操作 kcompactd触发的规整
migrate_sync 同步迁移,迁移过程会发生阻塞,若需要迁移的某个page正在writeback或被locked会等待它完成 sysfs主动触发的内存规整
migrate_sync_no_copy 同步迁移,但不等待页面的拷贝过程。页面的拷贝通过回调migratepage(),过程可能会涉及dma migrate_vma_pages
3.2 实现流程
内核文档有描述这个api是怎么工作的。不过这个描述着实是不太友好, 不容易在脑海形成画面。
我们通过结合代码实现,把这个转化为流程图:
总结一下,页面迁移过程本质就是分配一个 new_page, 解除原有 page 映射,把旧 page 复制到新 page 并建立新 page 的映射。
4. 页面迁移过程用户态访问处理
到这里可能会有疑问:如果在页面迁移过程中,应用发生发访问这个迁移中的页面,会发生什么?
情景1: 旧页面的页表还未解映射, 此时发生缺页可以正常访问原来页面。
情景2: 旧页面解除了映射,但新页面还未建立映射。这时访问会发生等待,需要等新页面建立映射并copy完成页面后才能访问。
情景3: 完成了页面迁移动作,可以正常访问新页面了。
下面我们重点分析一下,当旧页面解除了映射,且新页面未建立映射这个过程中发生了用户态访问,内核的处理流程是怎样的。
首先我们看一下旧页面解除了映射的过程:
static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, unsigned long address, void *arg){... if (pagehwpoison(page) && !(flags & ttu_ignore_hwpoison)) {... } else if (pte_unused(pteval) && !userfaultfd_armed(vma)) {... } else if (is_enabled(config_migration) && (flags & (ttu_migration|ttu_split_freeze))) { // 页面迁移会设置ttu_migration标记,走到这个分支来 swp_entry_t entry; pte_t swp_pte; if (arch_unmap_one(mm, vma, address, pteval) orig_pte); if (unlikely(non_swap_entry(entry))) { // 不是传统的swap entry if (is_migration_entry(entry)) { // 是迁移标记进来的 /* 等待migration的完成。本质是在等待旧page释放其page lock * 最终调用到 wait_on_page_bit_common */ migration_entry_wait(vma->vm_mm, vmf->pmd, vmf->address); } ...} 总结一下:
页面迁移前,首先会获取旧页面和新页面的页面锁 pg_lock,在解除映射的时候传入了由于页面迁移导致的解映射标记 ttu_migration,设置了此标记会生成一个带页面迁移标识的 swap_entry 设置到 pte 中。在设置好的那一刻走,应用进程无法很顺利地访问这个页面了,需要通过 do_swap_entry 路径。
假如此时应用进程访问了这个页面,会走进到 do_swap_entry,取出带迁移标识的 swap_entry,识别到这个标识,会等待页面锁释放。页面锁只有在页面迁移完成后才会被释放,也就是会发生等待直到页面迁移完成。
5. 用户态如何避免发生页面迁移
上面我们已经知道,如果有页面迁移过程中发生用户态访问,很可能是需要发生等待其迁移完成, 这个过程需要一定耗时。而有时的场景我们是需要避免此种时延抖动,那有什么办法呢?
方法就是让这个页面短时间内变得不可移动。
int migrate_page_move_mapping(struct address_space *mapping, struct page *newpage, struct page *page, int extra_count){... if (page_count(page) != expected_count) return -eagain;... return migratepage_success;} 可以看到当发生页面复制过程中,如果 page 的引用计数不符合预期(期望为0)时,这时系统认为有人在使用,不适用做迁移。那么,我们只需要增加 page 的引用计数就可以。
可以在不想被迁移的时间段开始前通过 pin_user_pages 这样的接口,结束时 unpin 就可以了。接口最终会调到 try_grab_page 增加引用计数。
微机保护硬件的构成
中兴通讯为赞比亚提供业界领先的定制化超100G骨干光网络建设方案
研华工控机IPC-510的配置参数|IPC-510产品说明书
面向PLC的自动代码生成基础
京东方意向收购显示器整机业务
内存内核中发生页面迁移的典型场景
一项名为EMAR项目的社会治疗机器人研究计划
变压器油色谱分析仪(工作原理_优点_应用_操作步骤_注意事项)
华为mate20受累屏幕或推动其强化与产业链的合作
到底是多核好还是高主频好
EDA技术FPGA设计有哪些应用?
裕太微电子联合申报项目荣获浙江省通信学会科学技术奖一等奖
0603封装 128种阻值 每种阻值500片 贴片电阻盒
TCL华星为moto三款新旗舰产品提供显示屏
苹果将取消3D Touch功能
abb变频器ACS510参数设置步骤
C语言入门教程-函数原型
华为荣耀8、华为Nova对比评测:荣耀8和华为Nova青春代表性价比谁将更胜一筹
电压随从器的隔离作用
MAX15054 高边MOSFET驱动器,用于HB LED驱