Linux中的malloc() - "无法保证内存真的可用"?

时间:2015-02-01 20:15:33

标签: c linux memory-management

我制作的游戏将世界划分为描述世界的数据块。我将块保存在动态分配的数组中,因此在初始化世界数据结构时我必须使用malloc()

阅读malloc() man page,附注如下:

  

默认情况下,Linux遵循乐观的内存分配策略。   这意味着当malloc()返回非NULL时,无法保证   内存确实可用。如果事实证明了   系统内存不足,一个或多个进程将被杀死   OOM杀手。有关更多信息,请参阅的说明   {em}中的 / proc / sys / vm / overcommit_memory / proc / sys / vm / oom_adj 以及Linux内核源文件   文档/ VM /过量使用计费

如果Linux设置为使用乐观内存分配,那么这是否意味着它始终不会返回我在调用proc(5)时请求的全部内存量?

我读到通过修改内核可以禁用乐观的内存分配,但我不想这样做。

那么有没有办法检查程序是否已分配所请求的金额?

2 个答案:

答案 0 :(得分:6)

从应用程序的角度来看,这不是您需要处理的事情。不希望随机进程被" OOM杀手"杀死的用户将通过

禁用过度使用
echo "2" > /proc/sys/vm/overcommit_memory

这是他们的选择,而不是你的选择。

但从另一个角度来看,这并不重要。典型"推荐"交换量是如此荒谬,以至于没有合理数量的malloc将无法拥有物理存储来支持它。但是,您可以轻松分配这么多(即使使用强制MAP_POPULATE或手动触摸它),以使系统保持交换数小时/天/周。没有规范的方法可以让系统通知您,如果您想要的内存量会使系统交换陷入困境,则会出错。

整个情况很糟糕,但作为应用程序开发人员,您在修复程序中的角色只是正确使用malloc并检查null返回值。其余的责任在于发行版和内核维护者。

答案 1 :(得分:1)

而不是malloc,您可以通过mmap直接分配必要的内存,MAP_POPULATE建议内核立即映射页面。

#include <sys/mman.h>

// allocate length bytes and prefault the memory so 
// that it surely is mapped
void *block = mmap(NULL, length, PROT_READ|PROT_WRITE, 
       MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE,
       -1, 0);

// free the block allocated previously
// note, you need to know the size
munmap(block, length);

但更好的选择是通常将世界保存到文件中,因此您可以直接从文件中mmap内容:

int fd = open('world.bin', 'r+');
void *block = mmap(NULL, <filesize>, PROT_READ|PROT_WRITE,
    MAP_SHARED, fd, 0);

文件world.bin从地址block开始映射到内存中;对内存的所有更改也会透明地写入文件 - 如果有足够的RAM,则无需担心,因为linux会自动映射页面进出。


请注意,除非您定义了某个功能测试宏,否则未定义其中一些标志:

  

某些标志常量仅在_BSD_SOURCE_SVID_SOURCE时定义   _GNU_SOURCE已定义。 (要求MAP_32BIT也足够了,并且要求宏具体更合乎逻辑,因为   这些标志都是特定于Linux的。)相关的标志是:   MAP_ANONYMOUSMAP_ANON(以及同义词MAP_DENYWRITE),   MAP_EXECUTABLEMAP_FILEMAP_GROWSDOWNMAP_HUGETLBMAP_LOCKED,   MAP_NONBLOCKMAP_NORESERVEMAP_POPULATEMAP_STACK和{{1}}。