XNU中UPL(Universal Page List)的作用及相关VM技术问询
关于XNU中UPL与虚拟内存管理的问题解答
作为长期研究XNU虚拟内存模块的开发者,我来帮你理清这些问题:
1. UPL(Universal Page List)的作用是什么?它是否与Linux中用于反向映射的anon_vma和PST节点相同?
UPL的核心作用是跟踪所有映射到同一物理页的虚拟地址条目,本质上是XNU实现反向映射(Reverse Mapping)的核心结构——当内核需要回收物理页、处理写时复制(COW)或者更新页映射时,它需要快速找到所有引用该物理页的虚拟地址,UPL就是干这个的。
它和Linux的anon_vma、PST(Page Structure Tree)有相似的设计目标,但并非完全相同:
- Linux的
anon_vma仅针对匿名页(未关联文件的内存页)的反向映射,而文件页的反向映射依赖于address_space结构下的映射链; - UPL的设计更通用,不管是匿名页还是文件-backed页,都可以通过UPL来追踪所有虚拟映射,不需要区分两种页类型的反向映射逻辑,这是XNU和Linux在反向映射实现上的关键差异。
所以结论是:UPL和Linux的反向映射结构核心目的一致,但设计更统一、适用范围更广。
2. XNU如何通过UPL结构查找虚拟地址?
每个物理页(vm_page结构)都会关联一个upl指针,指向对应的upl结构。upl结构内部维护了一个upl_entries链表,每个upl_entry都关联到一个vm_map_entry(代表一段虚拟地址范围的映射条目)。
查找虚拟地址的流程大致是这样的:
- 拿到目标物理页的
vm_page实例,通过vm_page->upl获取对应的UPL结构; - 遍历
upl->upl_entries链表中的每个upl_entry; - 每个
upl_entry都持有指向vm_map_entry的指针,从vm_map_entry中可以直接读取到该映射的虚拟地址起始、结束范围,以及所属的地址空间(vm_map); - 如果需要更精确的单个虚拟地址,还可以结合
vm_map的结构,进一步定位到具体的页表条目对应的虚拟地址。
这个过程最常见的应用场景是页面回收:当内核要回收一个物理页时,会通过UPL找到所有引用它的虚拟地址,逐一标记页表条目为无效,避免用户态访问出错。
3. 若第一个问题的答案为否,XNU如何编辑pmap条目以实现页面换入/换出?
虽然第一个问题的答案是“核心目的一致但设计不同”,但我还是可以给你讲讲XNU中页面换入换出时编辑pmap条目的逻辑:
- 换出(Page Out):
- 首先通过UPL找到所有映射目标物理页的虚拟地址条目;
- 对每个
vm_map_entry对应的虚拟地址范围,调用pmap_remove()或者pmap_clear()接口,将对应的页表条目(pmap条目)标记为无效,并清除TLB缓存; - 将物理页的内容写入交换空间(swap),更新
vm_page的状态为“已换出”,记录交换空间中的位置;
- 换入(Page In):
- 当用户态访问被换出的页触发缺页中断时,内核从交换空间读取数据到新分配的物理页;
- 再次通过UPL找到所有需要映射该物理页的虚拟地址条目;
- 调用
pmap_enter()接口,将新的物理页地址写入对应的页表条目,更新TLB缓存,恢复虚拟地址到物理页的映射。
这里的pmap是XNU中负责硬件页表管理的抽象层,不同架构(x86_64、ARM64)的pmap实现会有差异,但上层逻辑是统一的。
内容的提问来源于stack exchange,提问作者Levi
相关产品推荐
相关产品推荐

