【问题标题】:The range of virtual memory address in userspace用户空间的虚拟内存地址范围
【发布时间】:2015-06-17 08:15:38
【问题描述】:

在linux中,用户空间的虚拟内存地址范围,也就是malloc返回的值的范围,和整个64位虚拟内存空间一样吗? 或者,是否有任何 64 位虚拟内存空间的子范围可以保证在用户空间中看不到?

欢迎回答UNIX系统或Windows系统。

当然,我不打算在某些产品中引入这样的错误代码。 我只是想象如果有空闲空间,我们可以使用该空间来存储flgas,例如用于惰性构造的is_constructed标志,并且可以节省很多空间。通常,即使我们只使用 1bit,也需要 1byte(堆栈)分配。此外,这种将值编码到内存地址中可能会导致错误的内存预取或分支错误预测。然后,我想检查节省内存带宽和 CPU 误预测哪个更大。

【问题讨论】:

  • 你应该解释你问的原因。
  • 即使有你的解释,我也不明白它与问题的关系。
  • 如果保证虚拟内存地址的高n位不使用,我们可以在指针的这n位中写入数据。
  • 没有高n位应该全0或全1。

标签: c linux memory


【解决方案1】:

虚拟地址的可能范围是处理器内核ABI特定。但我强烈建议不要编写一些与地址和指针中的某些位相关的技巧(因为您的代码可能适用于某些处理器,但不适用于其他处理器)。

这些天,一些 *x86-64 处理器显然只使用 48 位的虚拟地址空间,但 我不建议使用它 em> 代码中的知识(几年内可能会出错,或者在某些高端模型上)。另见x86-64 ABI

如果指针超出 48 位范围,则会出现页面错误,即 SIGSEGV,处理器不会忽略未实现的位。所以指针或地址的高位应该全为零或全一。

在 Linux 上,您可以使用 cat /proc/self/mapscat /proc/$$/maps 来获得更多线索。

顺便说一句,在 Linux 上,您可以使用 mmap(2)MAP_ANONYMOUS | MAP_NORESERVE 来保留一些较大的地址范围(或者稍后调用 mmap 并在其中使用 MAP_FIXED,或者永远不要使用它)以避免它稍后出现由您的进程使用(或者,正如 damon 所评论的,使用 x86-64 特定的 MAP_32BITS)这可能比将地址位限制为 48 位更明智。

此外,在 Linux 上捕获 SIGSEGVtricky(您需要一些特定于处理器的代码)并且成本高昂。也许你想要一些external pager mechanism(它存在于 GNU Hurd,但不存在于 Linux)。或者 mmap-ing 在一些 FUSE 文件系统上的一些伪文件。

注意:大多数 x86-64 处理器只有 48 位地址,但我不建议使用。

注 2:处理器制造商记得 IBM/360 所做的:忽略高地址位(最初是 24 位)。当 IBM 不得不将地址扩展到 31 位时,这对软件行业来说是一场噩梦。所以硬件制造商明白了这个教训,并不允许今天(在硬件中)对未使用的地址位玩顽皮的把戏。

【讨论】:

  • 注意:除了使用MAP_FIXED,您还可以使用MAP_32BIT,这将保证高32位为零(有效地返回一个32位指针)。
  • Basile:您的问题以及此答案中的内容假定在解引用/指针算术的意义上在然后“使用”的指针的高位中对额外数据进行编码等等。我同意这很糟糕。知道指针仅在其 64 位中变化 48 位仍然很有用,因此您可以将指针值与其他 16 位信息一起存储在 uint64_t 中,并在使用前进行适当的屏蔽以提取原始指针值。如果运气好的话,您甚至可以尝试将这些值存储在指针类型中,尽管这样做的风险相当大。
猜你喜欢
  • 1970-01-01
  • 2023-03-17
  • 2019-07-03
  • 2016-06-02
  • 2011-12-27
  • 1970-01-01
  • 2021-09-11
  • 2014-01-16
  • 2011-08-09
相关资源
最近更新 更多