【问题标题】:How can we specify physical address for variable?我们如何为变量指定物理地址?
【发布时间】:2012-12-19 06:30:34
【问题描述】:

欢迎任何建议/讨论!

这个问题实际上就像标题一样简短,但我会解释为什么我需要实际地址。


背景

这些天我对缓存和多核架构着迷,现在我很好奇缓存在并行环境下如何影响我们的程序。

在某些 CPU 型号(例如,我的 Intel Core Duo T5800)中,L2 缓存在内核之间共享。因此,如果程序 A 正在访问物理地址的内存,例如

0x00000000, 0x20000000, 0x40000000...

和程序 B 在

处访问数据

0x10000000, 0x30000000, 0x50000000...

由于这些地址共享相同的后缀,L2缓存中的相关集合会被频繁刷新。我们预计会看到两个程序互相争斗,从内存而不是缓存中缓慢读取数据,尽管它们在不同的内核中是分开的。

然后我想在实践中验证结果。在这个实验中,我必须知道物理地址而不是虚拟地址。但是我该如何应对呢?


第一次尝试:

从堆中吃掉一大块空间,掩码,得到某个地址。

我的 CPU 有一个大小为 2048KB 且关联性为 8 的二级缓存,因此像 0x12340000, 0x12380000, 0x123c0000 这样的物理地址将与二级缓存中的第一组相关。

int HEAP[200000000]={0};
int *v[2];
int main(int argc, char **argv) {

    v[0] = (int*)(((unsigned)(HEAP)+0x3fffc) & 0xfffc0000);
    v[1] = (int*) ((unsigned)(v[0]) + 0x40000); 

    // one program pollute v[0], another polluting v[1]
}

遗憾的是,在虚拟内存的“帮助”下,变量HEAP 在物理内存中并不总是连续的。 v[0]v[1] 可能与不同的缓存集有关。


第二次尝试

访问/proc/self/mem,并尝试获取内存信息。

嗯……看来结果还是关于虚拟内存的。

【问题讨论】:

  • 我不认为您可以指定物理地址,至少在没有内核更改的情况下不能。但是您可以使用 /proc/self/maps 批量了解物理地址
  • @anishsane 嗯,我转储了/proc/self/maps,但它与物理地址有什么关系?第一个字段似乎是虚拟地址,那么dev字段与内存设备有关吗?
  • 哦,对不起,是的,前 2 个字段确实是虚拟地址...我曾用它来获取一些虚拟地址,这些地址与我打开的 PCI 设备的物理条地址相对应...抱歉误导。 ..
  • 在现代桌面 CPU 上以物理地址级别操作并不容易。在编写汇编程序时,在小型微控制器上很容易,但您不会在那里观察到缓存(我知道的那些没有缓存)效果。

标签: c linux performance caching memory-address


【解决方案1】:

您对内存和这些地址的理解不完整/不正确。本质上,您尝试测试的内容是徒劳的。

在用户模式进程的上下文中,您看到的几乎每个地址都是virtual address。也就是说,只有在该过程的上下文中才有意义的地址。操作系统管理此虚拟内存空间(进程独有)映射到内存页面的位置。这些内存页面在任何给定时间可能映射到页面调入(即驻留在物理 RAM 中) - 或者它们可能被调出,并且仅存在于磁盘上的交换文件中。

因此,为了解决 背景 示例,这些地址来自两个不同的进程 - 尝试比较它们绝对没有任何意义。它们的代码是否存在于任何缓存中取决于许多因素,包括处理器的cache-replacement strategy、操作系统启用的缓存策略、其他进程的数量(包括内核模式线程)等.

在您的第一次尝试中,再一次,您无法直接实际测试 CPU 缓存。首先,您的大缓冲区不会在堆上。它将成为可执行文件的数据部分(特别是 .bss)的一部分。堆用于malloc() 系列的内存分配。其次,是否分配一些巨大的 1GB 区域并不重要,因为尽管它在进程的虚拟地址空间中是连续的,但操作系统可以在它认为合适的地方分配虚拟内存页面 - 这可能 不实际上是连续的。同样,您几乎无法控制来自用户空间的内存分配。 “Is there a way to allocate contiguous physical memory from userspace in linux?”简短的回答是否定的。

/proc/$pid/maps 也不会把你带到任何地方。是的,那里列出了很多地址,但同样,它们都在进程$pid 的虚拟地址空间中。有关这些的更多信息:How do I read from /proc/$pid/mem under Linux?

【讨论】:

  • 你是对的,如果我们只是尝试访问单个地址,它可能会被分派给其他进程。但是,我尝试访问的是某种类型的物理地址(如 0x????0000)。如果我们知道大数组中的哪个位置与我们的条件匹配,将会有所帮助。
  • "我尝试访问的是某种类型的物理地址" 不。您尝试从用户模式程序访问的任何地址不是物理地址。这是一个虚拟地址,您不知道它将映射到物理地址空间的哪个位置。
  • 嗯,当我们有足够的资源(比如超过2个核心,很多内存)时,我们可以假设os不会page-out/re-map页面,并且环境会稳定够了吗?
  • 核心数与内存分页无关。事实上,更多的 CPU 内核可能会使事情有可能将进程分页。当然,如果您有无限的 RAM,那么您的交换分区利用率几乎为零。但这对你有什么好处?如果您想查看缓存性能,您可以简单地在第一次循环中执行某些代码,并将其与后续迭代进行比较。
  • 这个问题越来越离题了。这些确实是理论问题,可以通过一些研究和阅读虚拟内存和缓存如何工作等来更好地回答。这里似乎没有实际的编程问题。
猜你喜欢
  • 1970-01-01
  • 2011-12-01
  • 2019-04-04
  • 2023-03-29
  • 2017-10-06
  • 1970-01-01
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
相关资源
最近更新 更多