出于某种原因,我需要知道某个变量的物理地址。尽管如此,物理地址在初始化变量后会发生变化。要获取物理地址,我使用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执行此代码。
这可能是一个愚蠢的问题,但我无法理解这种行为背后的原因。
答案 0 :(得分:5)
除非您锁定内存(mlock(2)
),否则物理地址可能会随时间而变化。
如果您的变量未初始化,它将驻留在BSS中,并且BSS页面最初将指向填充了零的共享页面。一旦您写入该页面,整个页面可能必须被复制到另一个页面框架(物理页面),因此不同的物理地址。
请注意,复制后页面中的相对偏移量保持不变:0x780
,正如从正确的代码中预期的那样。
答案 1 :(得分:3)
我要说的第一件事就是打印指针(地址)是
%p
格式说明符。(void *)
。如果不这样做,你就会导致undefined behavior并且无论如何都无法证明输出是正确的。
即如other answer by @Anti所述,这里的物理内存“备份”虚拟内存无需修复。基于分配内存的类型的类型(行为),可以基于实现在后台更改物理内存。这就是为什么我们在应用程序代码中使用虚拟内存并让OS / MMU处理底层的映射和转换。