【问题标题】:why physical address value is different depending on how it was printed为什么物理地址值因打印方式而异
【发布时间】: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 &amp;physAddr。此外,phys_addr_tu32u64,因此转换为 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


【解决方案1】:

来自kmalloc 且值为0x10 的虚拟地址(virtAddr) 没有意义。那么,在那之后,所有的赌注都取消了吗?

你确定你有phys_addr_t physAddr(与(例如)phys_addr_t *)?在我假设的堆栈上?

%pap 的输出看起来像一个 [stack] 虚拟地址而不是物理地址。所以,我关于&amp;physAddr/physAddr原始顶级评论可能会根据您的完整代码而有所影响。

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

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

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


旁注:这是编辑之前的原始帖子[被否决] [有一些澄清],但它仍然值得尝试。

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

变化:

struct SizeAddr

进入:

union SizeAddr

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

【讨论】:

  • 我为什么要这样做?那只会将所有内容存储在一个位置。
  • 这并不能回答问题,即使作为对 OP 代码的评论,它的质量也值得怀疑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
  • 2018-11-02
  • 2012-10-27
  • 2014-05-17
  • 1970-01-01
相关资源
最近更新 更多