首先,我要说的是,我非常清楚VirtualAlloc()
如何工作以及现代操作系统的虚拟内存设施如何工作。
说,使用MAP_RESERVE
Windows API的VirtualAlloc()
标志,而还使用MEM_COMMIT
,今天有一些实际用途吗?
我的意思是,当我用VirtualAlloc()
调用MEM_RESERVE|MEM_COMMMIT
时,我既保留并提交页面,但是我知道操作系统只会在我尝试时才真正分配页面写进去。
这种优化几乎发生在所有现代操作系统上。
因此,考虑到这一优化问题,如果我使用VirtualAlloc()
调用MEM_RESERVE
,然后我使用MEM_COMMIT
多次调用它来提交页面,则不是相同仅调用VirtualAlloc()
一次的结果,指定MEM_RESERVE|MEM_COMMIT
?
由于仅指定MEM_RESERVE
将仅保留页面边界地址,而不提交实际页面,但是MEM_RESERVE|MEM_COMMIT
将仅保留+提交我写入的页面,而不是使用{{1}单独,今天浪费时间?
只有 1 使用MEM_RESERVE
调用VirtualAlloc()
我基本上可以获得与MEM_RESERVE|MEM_COMMIT
一次调用VirtualAlloc()
并将其称为几个N的相同结果时间MEM_RESERVE
。
作为我所说的内容的证明,我注意到MEM_COMMIT
工具在使用MEM_RESERVE
系统调用的Unices / POSIX系统中根本不存在。
在那里你可以"提交"一大块页面调用mmap(2)
一次,然后只有在你写入页面时才真正分配页面,这些页面都是由操作系统优化的。
所以,单独使用mmap(2)
只是旧时的事情只有在内存页面是宝贵的资源时才有用,所以今天没用?
或者,单独使用此标记(然后使用MEM_RESERVE
调用VirtualAlloc()
N次)仍有一些我遗漏的实际用途?
答案 0 :(得分:3)
当您提交内存时,内存管理器不会立即为您分配实际页面,但是it does count them towards the total number available.内存管理器将永远不会提交比实际存在的页面更多的页面,并且当您访问已提交的页面时可以保证,记忆就在那里。
MEM_RESERVE
的目的是分配虚拟内存地址。您可以根据需要保留尽可能多的地址空间,即使您没有多太字节的实际空间,也可以在64位系统上保留多达数TB的数据。
默认情况下,Linux不会将分配限制为可用的实际空间量。此“功能”称为 overcommit 。这意味着在Linux上没有单独的保留和提交步骤。如果要在Linux上保留地址空间another question recommends mmap
ping an area with no permissions.。
答案 1 :(得分:0)
除了前面的答案,这里还有Microsoft docs的引文:
作为动态分配的替代方法,该过程可以简单地提交整个区域,而不仅仅是保留它。 这两种方法导致相同的物理内存使用,因为已提交的页面在首次访问之前不会消耗任何物理存储。动态分配的优势在于,它可以最大程度地减少系统上已提交页面的总数。对于非常大的分配,预先提交整个分配会导致系统用尽可提交页面,从而导致虚拟内存分配失败。