我想使用mmap函数将文件映射到内存中,并想知道当前平台上的虚拟内存量是否足以映射大文件。对于32系统,我无法映射大于4 Gb的文件
请std::numeric_limits<size_t>::max()
给我一定数量的可寻址内存,还是我应该测试的其他类型(off_t或其他)?
正如列瑞恩在评论中指出的那样,“虚拟记忆”在这里被误用了。然而,问题是:有一个与指针相关联的类型,它具有最大值,用于定义您可以在系统上添加的内容的上限。这是什么类型的?是size_t还是ptrdiff_t?
答案 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)
事实上,指针的大小不会告诉您实际可用的“地址空间”的大小,即可以映射为单个连续的块。
受限于:
最后,不要混淆“可用内存”和“可用地址空间”。做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*)
。这将为您提供目标平台上指针的长度(以字节为单位)。因此,您可以找出可寻址空间有多大。