【发布时间】:2016-12-26 23:46:59
【问题描述】:
我正在使用 x86 架构。据我了解(并且被告知)要获得分配内存的物理地址,我需要执行以下操作:
struct SizeAddr {
size_t size;
u64 addr_uint64;
void* addr_voidp;
unsigned long addr_ul;
};
struct SizeAddr sa;
virtAddr = kmalloc(<some size>, GFP_KERNEL);
physAddr = virt_to_phys(virtAddr);
sa.addr_uint64 = (uint64_t)physAddr;
sa.addr_voidp = (void *)physAddr;
sa.addr_ul = (unsigned long)physAddr;
我决定打印出物理地址的值,所以我做了以下操作:
printk(MODULE_NAME " virtAddr(%%p) = %p\n", virtAddr);
printk(MODULE_NAME " physAddr(%%pap) = %pap\n", &physAddr);
printk(MODULE_NAME " physAddr(%%llx) = %llx\n", sa.addr_uint64);
printk(MODULE_NAME " physAddr(%%p) = %p\n", sa.addr_voidp);
printk(MODULE_NAME " physAddr(%%lx) = %lx\n", sa.addr_ul);
这是我在日志中得到的:
[63898.990593] my_kmodule virtAddr(%p) = 0000000000000010
[63898.990652] my_kmodule physAddr(%pap) = ffff88020d783eb0
[63898.990711] my_kmodule physAddr(%llx) = 780000000010
[63898.990768] my_kmodule physAddr(%p) = 0000780000000010
[63898.990827] my_kmodule physAddr(%lx) = 780000000010
这就是我真正感到困惑的地方。所有这些值不应该相同吗?为什么physAddr(%pap) 与其他值不同(我理解的虚拟地址除外)。
【问题讨论】:
-
你没有显示分配
sa的代码。 -
printk#2 错误。你想要physAddr而不&physAddr。此外,phys_addr_t是u32或u64,因此转换为u64并尝试%llx。 -
我不知道
pap是什么,但打印指针值的方法是使用printf("%p", (void*)virtAddr); -
另外,
%pap怎么不解释为有效格式代码%p后跟ap。?如果我想打印一个指针值后跟文字字符ap,该怎么办? -
@WeatherVane 这不是
printf,而是printk。一个用于用户空间,另一个用于内核空间。要了解pap是什么,请查看 kernel.org/doc/Documentation/printk-formats.txt
标签: c linux linux-kernel linux-device-driver device-driver