Linux内核判断物理页使用方法
Linux内核中如何快速判断物理页是否在被使用
在Linux内核中,判断一个物理页(由 struct page
表示)是否正在被使用,主要通过检查其引用计数(Reference Count)来实现。以下是详细方法和关键点:
核心方法:检查引用计数
使用
page_count()
函数
Linux内核提供了辅助函数page_count()
直接获取页面的引用计数:1
2
3
int active = page_count(page); // 返回引用计数值- 返回值含义:
- **
> 0
**:页面正在被使用(至少有一个引用)。 - **
= 0
**:页面未被使用(空闲状态,可能已被释放或可被回收)。
- **
- 返回值含义:
直接访问
_refcount
成员
某些场景可能需要更精细的控制,可直接访问struct page
的引用计数成员(不同内核版本字段名可能不同):1
2
3
4
5// 内核版本 >= 4.6
atomic_t refcount = page->_refcount;
// 旧版本(如 < 4.6)
atomic_t refcount = page->_count;通过原子操作读取值:
1
int count = atomic_read(&page->_refcount);
引用计数的来源
引用计数增加的情况包括:
- 内核直接引用:通过
get_page()
或try_get_page()
显式增加计数。 - 页表映射:用户空间或内核空间映射该页(如进程的页表项指向该页)。
- I/O 操作:正在进行磁盘I/O(如
struct bio
持有该页)。 - 缓存关联:页面在页缓存(Page Cache)或匿名页链表中。
注意事项
并发安全
引用计数通过原子操作更新,确保多线程环境下的安全性。直接访问时需使用原子函数(如atomic_read()
)。复合页(Compound Pages)
大页(如THP)由多个子页组成,主页的引用计数代表整个复合页。使用page_count()
已自动处理此情况。0
计数的特殊含义
计数为0
的页面通常处于空闲状态,但需注意:- 可能位于伙伴系统(Buddy System)的空闲链表上。
- 某些短暂状态(如正在释放)也可能短暂出现
0
。
避免直接比较计数值
推荐使用page_count(page) > 0
而非== 1
,因为页面可能被多次引用(如共享内存)。
示例代码
1 | // 判断页面是否正在被使用 |
其他辅助方法
- 页标志位检查:
通过PageXXX()
宏检查页状态(如PageActive()
、PageLRU()
),但无法直接替代引用计数。 - 映射状态检查:
使用page_mapped()
检查是否被页表映射,但仅覆盖部分使用场景(如未映射的页缓存页仍可能被使用)。
总结
**快速判断物理页是否被使用的标准方法是检查 page_count(page) > 0
**。该操作高效且线程安全,适用于大多数场景(如内存回收、调试等)。对于复杂需求(如精确追踪引用来源),可结合页标志位或内核工具(如 page_owner
调试功能)。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Helloeuler!