初始化变量时,物理地址会有所不同

时间:2018-01-15 09:33:48

标签: c linux memory heap-memory

出于某种原因,我需要知道某个变量的物理地址。尽管如此,物理地址在初始化变量后会发生变化。要获取物理地址,我使用this function (virt_to_phys(..., uint64_t virtaddr)),这似乎正常。行为的一些例子:

在初始化之前: virtual 0x5632692a3780 physical 0x32b2c7c780

初始化后: virtual 0x5632692a3780 physical 0x342147a780

使用这些格式化程序:

printf("virtual 0x%llx physical 0x%llx\n", &p, virt_to_phys((uint64_t) &p));

我正在使用-O2进行编译,但我也使用了-O0并且没有任何更改,所以我猜这种行为不是优化。我也在Arch Linux中使用内核4.13.4-1执行此代码。

这可能是一个愚蠢的问题,但我无法理解这种行为背后的原因。

2 个答案:

答案 0 :(得分:5)

除非您锁定内存mlock(2)),否则物理地址可能会随时间而变化。

如果您的变量未初始化,它将驻留在BSS中,并且BSS页面最初将指向填充了零的共享页面。一旦您写入该页面,整个页面可能必须被复制到另一个页面框架(物理页面),因此不同的物理地址。

请注意,复制后页面中的相对偏移量保持不变:0x780,正如从正确的代码中预期的那样。

答案 1 :(得分:3)

我要说的第一件事就是打印指针(地址)是

  • 使用%p格式说明符。
  • 将相应的参数投射到(void *)

如果不这样做,你就会导致undefined behavior并且无论如何都无法证明输出是正确的。

即如other answer by @Anti所述,这里的物理内存“备份”虚拟内存无需修复。基于分配内存的类型的类型(行为),可以基于实现在后台更改物理内存。这就是为什么我们在应用程序代码中使用虚拟内存并让OS / MMU处理底层的映射和转换。