在 printk 中使用 %p 格式占位符用于打印指针值,但其行为与用户空间的 printf 不同,默认会对地址进行哈希处理,以防止泄露内核内存布局的敏感信息。
%p 的行为
默认哈希:%p 不会直接打印指针的真实内存地址,而是输出一个经过哈希处理的值。例如:abcdef12 或 00000000abcdef12(在64位系统上,高32位通常被清零)。
安全目的:这是内核的安全机制,避免攻击者通过内核日志获取真实地址,从而利用内存漏洞。
唯一标识符:哈希后的值仍能作为该指针的唯一标识符,便于调试时追踪对象。
如何打印真实地址?
如果调试时需要查看指针的真实内核虚拟地址,应使用以下替代格式:
%px:推荐方式,直接打印指针的原始值,无需强制类型转换。例如:
cCopy Code
pr_info("Real address: %px\n", my_pointer);
输出示例:0xffffff8018f4b000(符合ARM64内核地址空间规范)
%lx:可作为备选,但需将指针显式转换为 unsigned long:
cCopy Code
pr_info("Real address: 0x%lx\n", (unsigned long)my_pointer);
虽然能输出正确地址,但不如 %px 简洁且易被工具(如 grep)识别。
其他相关指针格式
格式
用途
示例输出
%pS
打印符号名 + 偏移(带函数名)
virtio_init+0x0/0x110
%ps
打印符号名(不带偏移)
virtio_init
%pB
打印栈回溯用的符号名(考虑尾调用优化)
prev_fn+0x88/0x88
%pK
打印内核指针(仅用于 procfs/sysfs,需权限)
0x...
%pe
打印错误指针(如 -ENOSPC)
-ENOSPC
总结
不要用 %p 查看真实地址 → 会输出哈希值。
调试内核地址时,优先使用 %px → 安全、直接、推荐。
仅在需要符号信息时使用 %pS 或 %pB → 更具语义价值。
⚠️ 注意:在用户空间程序中,%p 会打印真实虚拟地址,但在内核空间中,安全策略强制哈希,这是有意设计,而非 bug。