do_pte_missing是handle_pte_fault()中用于处理PTE 缺失(pte_none)或仅包含 PTE marker情况的入口函数。它的核心职责是:根据 VMA 的类型,将缺页分派给匿名页处理路径或文件映射处理路径。
核心实现
static vm_fault_t do_pte_missing(struct vm_fault *vmf) { if (vma_is_anonymous(vmf->vma)) return do_anonymous_page(vmf); else return do_fault(vmf); }分派逻辑
函数基于一个简单的判断:该 VMA 是匿名映射还是文件映射。
匿名 VMA(
vma_is_anonymous为真):调用do_anonymous_page(vmf),为匿名页缺页分配新的物理页面(或复用零页)。文件 VMA:调用
do_fault(vmf),从文件的 page cache 中读取页面,或处理写时复制。
历史背景与设计意图
这个函数是在PTE marker 机制引入后从handle_pte_fault()中抽取出来的。
在 PTE marker 出现之前,handle_pte_fault()中的逻辑是:如果pte_none(entry)为真,则根据 VMA 类型调用do_anonymous_page或do_fault。但 PTE marker 是一种特殊类型的“非存在” PTE——它不映射任何物理页,却携带了 uffd-wp 等元数据。在大多数情况下,PTE marker 应被当作nonePTE 处理。
do_pte_missing的引入统一了这两种情况的处理:无论是真正的空 PTE,还是仅包含 marker 的 PTE,都走同一套分派逻辑。函数名中的 “missing” 正是指“PTE 缺失或仅有 marker”这一语义。
调用上下文
在handle_pte_fault()中,do_pte_missing被调用的条件是 PTE 既不是 present,也不是真正的交换项:
if (pte_none(entry)) { /* pte_none 或 pte marker */ return do_pte_missing(vmf); }如果 PTE 是 present,会走do_wp_page或其他路径;如果是真正的交换项(is_swap_pte),则走do_swap_page。
与相关函数的关联
do_anonymous_page:你已经了解过,负责匿名页缺页的核心分配逻辑,内部会检查vmf_pte_changed来处理并发竞态。do_fault:文件映射缺页的入口,会调用vma->vm_ops->fault从文件系统读取页面。handle_pte_marker:如果 PTE 是 marker 且需要特殊处理(如 uffd-wp 确认清除),会在handle_pte_fault的更早阶段被拦截,不会进入do_pte_missing。
总结来说,do_pte_missing是缺页处理路径中一个简洁而关键的分派节点:它把“PTE 不存在(或仅有 marker)”这一状态,根据地址空间类型,路由到正确的底层处理函数。