如何通过struct page判断物理内存页面是否处于pinned状态
关于Linux物理页面pinned状态的常见问题解答
1. 物理页面pinned状态判断方法
pinned状态的核心特征是页面不可被交换到swap分区、不可被内存迁移机制移动,你可以通过两个内核层面的标识判断该状态:
struct page结构体的_refcnt引用计数字段:通过get_user_pages()系列接口钉住的用户态页面,内核会对该字段执行+1操作,只要_refcnt数值大于1,就代表有内核态逻辑持有该页面的有效引用,内存回收、迁移流程都会跳过该页面。- 页面标志位:如果
PageLocked()宏判断返回真,或是页面设置了PG_pinned、PG_mlocked专属标志,也可判定页面处于pinned状态。
2. 其他需要钉住页面的场景
除了用户态内存用于DMA传输的场景外,内核态分配的内存如果要用于DMA操作,也需要做pinned处理,不同分配接口的处理逻辑有差异:
kmalloc分配的内存
kmalloc分配的是物理地址连续的低端内存,本身默认不会被交换到swap分区。如果要用于DMA操作,调用dma_map_single()做地址映射时,内核会自动完成pinned逻辑,不需要额外手动调用引用计数增加接口。注意DMA操作结束后必须调用dma_unmap_single()解除映射,否则页面会一直被钉住,造成内存泄漏。
vmalloc分配的内存
vmalloc分配的是虚拟地址连续、物理地址不连续的高端内存,默认支持内存回收逻辑。如果要用于DMA操作,需要先遍历vmalloc虚拟地址范围对应的每一个物理页,手动调用get_page()接口增加每个物理页的引用计数完成钉住,再做DMA映射。操作完成后要依次调用put_page()释放每个物理页的引用,避免内存泄漏。
除此之外还有几类常见的页面pinned场景:
- 进程调用
mlock()/mlockall()系统调用锁定的用户态内存页,会被设置PG_mlocked标志,长期处于pinned状态,不会被换出。 - 内核slab分配器中标记为不可回收的slab页、内核栈页、内核代码段/数据段对应的物理页,默认就处于pinned状态。
内容的提问来源于stack exchange,提问作者Dillion Wang
相关产品推荐
相关产品推荐

