如何获得C ++中可用的虚拟内存量?

时间:2010-11-18 13:15:36

标签: c++ memory memory-management virtual-memory

我想使用mmap函数将文件映射到内存中,并想知道当前平台上的虚拟内存量是否足以映射大文件。对于32系统,我无法映射大于4 Gb的文件 请std::numeric_limits<size_t>::max()给我一定数量的可寻址内存,还是我应该测试的其他类型(off_t或其他)?

正如列瑞恩在评论中指出的那样,“虚拟记忆”在这里被误用了。然而,问题是:有一个与指针相关联的类型,它具有最大值,用于定义您可以在系统上添加的内容的上限。这是什么类型的?是size_t还是ptrdiff_t?

5 个答案:

答案 0 :(得分:1)

嗨,如果你在win32中编码,你可以使用GlobalMemoryStatusEx和VirtualQueryEx

答案 1 :(得分:1)

size_t只需要足够大以存储最大可能的单个连续对象。 可能与地址空间的大小不同(例如,在具有分段内存模型的系统上)

但是,在具有平坦内存空间的常见平台上,两者是相等的,因此如果您知道目标CPU,则可以在实践中使用size_t

无论如何,这并没有真正告诉你任何有用的东西。当然,32位CPU具有4GB的内存空间,因此size_t是32位无符号整数。但这并没有说明你可以分配多少钱。操作系统使用内存空间的某些部分。您自己的应用程序已经使用了一些部分:将可执行文件映射到内存(以及它可能使用的任何动态库),每个线程的堆栈,堆上分配的内存等等。

所以不,像size_t的大小这样的技巧会告诉你一些你正在运行的地址空间,但没有什么可用的。您可以向操作系统询问您的流程和其他指标使用了多少内存,但同样,这对您没有多大帮助。一个进程有可能只使用几兆字节,但是如果分布在这么多的小分配上,就不可能找到大于100MB的连续内存块。因此,在32位计算机上,使用几乎没有内存的进程,您不太可能进行这样的分配。 (即使操作系统有一个神奇的WhatIsTheLargestPossibleMemoryAllocationICanMake() API,仍然也无法帮助你。它会告诉你刚才需要的 。您无法保证在您尝试映射文件时答案仍然有效。

所以,你可以做的最好的事情是尝试来映射文件,看看它是否失败。

答案 2 :(得分:1)

事实上,指针的大小不会告诉您实际可用的“地址空间”的大小,即可以映射为单个连续的块。

受限于:

  • 操作系统。它可以选择仅为您提供理论上可能的地址范围的子集,因为OS自身需要可映射的内存(例如,使图形卡帧缓冲可见,当然也可供操作系统本身使用) )。
  • 可配置的限制。在Linux / UNIX上,使用“ulimit”命令。 setrlimit()系统调用允许以各种方式限制应用程序地址空间的最大大小,Windows通过注册表参数具有类似的选项。
  • 申请的历史。如果应用程序广泛使用内存映射,则地址空间可能会限制“可用”连续虚拟地址的最大大小。
  • 硬件平台。有些CPU的地址空间有“漏洞”;一个例子是64位x86,其中指针仅在0x0..0x7fffffffffff或0xffff000000000000和0xffffffffffffffff之间有效。即你有2x128TB而不是完整的16EB。把它想象成48位“签名”指针......

最后,不要混淆“可用内存”和“可用地址空间”。做malloc(someBigSize)和mmap(...,someBigSize,...)之间有区别,因为前者可能需要物理内存的可用性来容纳请求,而后者通常只需要足够大的可用性地址范围。

对于UNIX平台,部分答案是使用getrlimit(RLIMIT_AS),因为这给出了应用程序当前调用的上限 - 如上所述,用户和/或管理员可以配置它。您可以保证任何mmap区域大于此的尝试都将失败。

答案 3 :(得分:1)

重新提出你的改编问题“你可以在你的系统上添加的内容的上限”,有点误导;它是特定的硬件架构。有64位架构(x64,sparc),其MMU乐于允许(uintptr_t)( - 1)作为有效地址,即您可以将某些内容映射到64位地址空间的最后一页。操作系统是否允许应用程序这样做是一个完全不同的问题......

对于用户应用程序,“高分”不是(始终)先验地固定。它是可调的,例如Solaris或Linux。这就是getrlimit(RLIMIT_AS)的用武之地。

再次注意,根据规范,没有什么可以防止(奇怪的)操作系统设计选择,例如将应用程序堆栈和堆放在“低”地址,同时将代码置于“高”地址,在具有地址空间漏洞的平台上。你需要完整的64位指针,不能让它们变小,但是可能存在任意数量的“无法访问/无效”范围,这些范围永远不会提供给你的应用。

答案 4 :(得分:0)

您可以尝试sizeof(int*)。这将为您提供目标平台上指针的长度(以字节为单位)。因此,您可以找出可寻址空间有多大。