为什么物理地址值根据打印方式而有所不同

时间:2016-08-19 18:15:02

标签: c linux linux-kernel linux-device-driver device-driver

我正在使用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)与其余值不同(虚拟地址除外,我理解的那个)。

1 个答案:

答案 0 :(得分:-2)

来自virtAddr的值为kmalloc的虚拟地址(0x10)毫无意义。所以,在那之后,所有的赌注都没有了?

您确定自己有phys_addr_t physAddr(对比(例如)phys_addr_t *)吗?在我认为的堆栈上?

%pap的输出看起来像[堆栈]虚拟地址而不是物理地址。因此,我的原始关于&physAddr/physAddr的最高评论可能会有一些影响,具体取决于您的完整代码。

printk("%p\n",&physAddr);说什么?或者,printk("%llx\n",(u64) &physAddr);?或者,其他组合(例如&virtAddr

虽然文档说%pap没问题,但它也说默认为phys_addr_t(即%pa)。两个应该工作[我对printk代码的检查似乎来确认这一点],%pap只有大约5个用法和数百个%pa

的用法

我已经检查了printk来源[重新检查,实际上,因为我之前必须多次这样做]。目前,我发现没有任何不符之处。但是,消息来源有点复杂,所以我会继续这样做。

旁注:这是编辑之前的原始帖子[正在进行下调] [有一些澄清],但仍然需要尝试。

现在您已添加了sa代码...

变化:

struct SizeAddr

分为:

union SizeAddr

添加phys_addr_t成员,并仅设置[使用union]。这是更常见的成语。然后,你会看到哪个被截断,哪个没有。否则,对于struct %llx,您将获得与%pap匹配的结果。