内核模块中判断struct page*是否为ZERO_PAGE及phys_base报错解决
解决内核模块中判断ZERO_PAGE时的
phys_base未定义错误 在RHEL 5.11(内核2.6.18-398.el5)环境下,你遇到的phys_base未定义问题,根源在于ZERO_PAGE()宏的实现依赖于内核内部符号phys_base,而该符号并没有被导出到内核模块可用的符号表中,导致模块编译和加载时无法解析它。
下面提供两种可行的解决方法:
方法一:使用导出的empty_zero_page变量获取ZERO_PAGE指针
在2.6.18版本的内核中,全局变量empty_zero_page指向了ZERO_PAGE的虚拟地址,并且这个符号是被导出的,可以直接在模块中使用。你可以将判断代码修改为:
#include <linux/mm.h> // 确保引入该头文件以获取empty_zero_page的定义 foo(struct page *pp, ..) { if (pp == virt_to_page(empty_zero_page)) { // 你的处理逻辑,比如预加载页 } }
这样就绕过了依赖phys_base的ZERO_PAGE()宏,直接通过导出的符号获取ZERO_PAGE对应的struct page*指针进行比较。
方法二:判断页内容是否全零(备选方案)
如果因为某些原因无法使用empty_zero_page,可以退而求其次,通过检查页的内容是否全部为零来判断是否是ZERO_PAGE。不过这种方法效率略低,适合对性能要求不高的场景:
#include <linux/uaccess.h> // 用于安全访问页内容 #include <linux/mm.h> foo(struct page *pp, ..) { void *page_addr = kmap(pp); // 映射页到内核虚拟地址 int is_zero = 1; unsigned long i; for (i = 0; i < PAGE_SIZE; i++) { if (((unsigned char *)page_addr)[i] != 0) { is_zero = 0; break; } } kunmap(pp); // 解除映射 if (is_zero) { // 你的处理逻辑 } }
注意:如果该页是用户空间页,需要确保访问操作的安全性;如果是内核页,直接映射访问即可。
额外说明
- 你的Makefile写法是正确的,不需要修改,问题完全出在内核符号导出的层面。
- 替换代码后,记得移除对
ZERO_PAGE()宏的依赖,确保只保留必要的头文件(比如linux/mm.h已经间接包含了多数页操作相关的定义)。
内容的提问来源于stack exchange,提问作者Pratik Shinde
相关产品推荐
相关产品推荐

