8

我想在我的进程中为以前使用但目前不需要的内存保留虚拟地址空间。我对主机内核是 Linux 的情况感兴趣,并且它被配置为防止过度使用(它通过详细说明所有已提交的内存来实现)。

如果我只是想防止我的应用程序不再使用的数据占用物理内存或被交换到磁盘(无论哪种方式都浪费资源),我可以madvise使用不需要它的内核,或者mmap在它上面添加新的零页。但是这两种方法都不一定会减少算作已提交的内存量,然后阻止其他进程使用这些内存量。

如果我用标记为只读的新零页替换这些页面怎么办?我的意图是它们不计入已提交的内存,并且我以后可以使用mprotect它们使它们可写,并且如果使它们可写将超过已提交的内存限制,它将失败。我的理解正确吗?这行得通吗?

4

2 回答 2

1

如果您不使用该页面(读取或写入它),它将不会被提交到您的地址空间(仅保留)。

但是你的地址空间是有限的,所以你不能随心所欲地玩。

参见例如 ElectricFence,由于插入“nul page/guard page”(无法访问的匿名内存),它可能会因大量分配而失败。看看这些线程:“mprotect() 失败:无法分配内存”: http ://thread.gmane.org/gmane.comp.lib.glibc.user/538/focus=976052

于 2011-02-10T14:58:22.640 回答
1

在 Linux 上,假设未禁用过度使用,您可以使用MAP_NORESERVE标志 to mmap,这将确保有问题的页面在被访问之前不会被计为分配的内存。如果 overcommit 已被完全禁用,请参阅下面的多映射页面。

请注意,过去 Linux 的零页行为有时会发生变化。对于某些内核版本,简单地读取页面会导致它被分配。对于其他人,写是必要的。请注意,保护标志不会直接导致分配;但是它们可以防止您意外触发分配。mprotect因此,为了获得最可靠的结果,您应该完全避免使用ing访问该页面PROT_NONE

作为另一个更便携的选项,您可以在多个位置映射同一页面。也就是说,创建并打开一个空的临时文件,将其取消链接ftruncate到一些合理数量的页面,然后mmap在文件的偏移量 0 处重复。这将绝对保证内存只计算一次程序的内存使用量。您甚至可以MAP_PRIVATE在写入页面时使用它来自动重新分配它。

但是,这可能比该MAP_NORESERVE技术具有更高的内存使用率(对于内核跟踪数据和临时文件本身的页面),因此我建议MAP_NORESERVE在可用时使用。如果您确实使用了这种技术,请尝试使被映射的区域相当大(并在 Linux 上将其放入/dev/shmif 中,以避免实际的磁盘 IO)。每个单独mmap的调用都会消耗一定数量的(不可交换的)内核内存来跟踪它,所以最好保持倒计时。

于 2011-02-10T15:05:28.617 回答