fork()失败并出现内存不足错误

时间:2013-03-25 05:39:14

标签: linux fork virtual-memory memory-overcommitment

父进程在尝试分叉子进程时失败并且errno = 12(内存不足)。父进程在Linux 3.0内核上运行 - SLES 11.在分叉子进程时,父进程已经占用了大约70%的RAM(180GB / 256GB)。这个问题有解决办法吗?

应用程序是用C ++编写的,用g ++ 4.6.3编译。

3 个答案:

答案 0 :(得分:11)

在系统中可能会阻止虚拟内存过度提交。

如果被阻止,则虚拟内存不能大于物理RAM +交换的大小。如果允许,则虚拟内存可能大于RAM + swap。

当您的进程分叉时,您的进程(父进程和子进程)将具有2 * 180GB的虚拟内存(如果您没有交换,那就太多了。)

所以,通过这种方式允许过度提交:

 echo 1 > /proc/sys/vm/overcommit_memory

如果子进程立即执行,或者在父对自己的内存写入太多之前释放已分配的内存,它应该会有所帮助。因此,请注意,如果两个进程都继续使用所有内存,则内存杀手可能会起作用。

proc(5)的手册页说:

  

/ proc / sys / vm / overcommit_memory

     

此文件包含内核虚拟   记忆计费模式。值为:0:启发式过度使用(这是   默认值)1:总是过度使用,从不检查2:始终检查,从不   过量使用

     

在模式0中,不检查具有MAP_NORESERVE的mmap(2)调用,并且   默认检查非常弱,导致获得a的风险   过程“OOM被杀”。在Linux 2.4下,任何非零值都意味着模式   1.在模式2(从Linux 2.6开始提供)中,系统上的总虚拟地址空间限制为(SS + RAM *(r / 100)),其中SS是   交换空间的大小,RAM是物理内存的大小,   和r是文件/ proc / sys / vm / overcommit_ratio的内容。

此处提供更多信息:Overcommit Memory in SLES

答案 1 :(得分:1)

fork - ing需要资源,因为它是copy-on-writing进程的可写页面。再次阅读fork(2)手册页。

你至少可以提供一个巨大的临时交换文件。您可以使用

创建(在某个文件系统上有足够空间)一个巨大的文件$SWAPFILE
  dd if=/dev/zero of=$SWAPFILE bs=1M count=256000
  mkswap $SWAPFILE
  swapon $SWAPFILE

否则,你可以用不同的方式设计你的程序,例如mmap - 一些大文件(和munmap - 在分叉之前,mmap之后再次使用它,或者更简单地从程序的开头开始popen {1}} - ed shell,或p2open - ed或明确表示pipe - 来自它(可能是一个多路呼叫àlapoll也很有用) ,然后向它发出命令。

如果我们知道你的程序在做什么,它为什么会消耗这么多内存,为什么以及它有什么分支......也许我们可以提供更多帮助......

阅读Advanced Linux Programming了解更多信息。

PS。

如果您fork仅运行gdb来显示回溯,请考虑更简单的替代方案,例如recent GCC's libbacktraceWolf's libbacktrace ......

答案 2 :(得分:0)

在Linux上,更好的解决方案是使用vfork或posix_spawn(因为如果可能,它将尝试使用vfork):vfork“在不复制父进程的页表的情况下创建新进程”,因此即使您使用应用程序使用了超过50%的可用RAM。

请注意,std :: system和QProcess :: execute也可以在后台使用fork,甚至在Qt框架中也有关于此问题的标签:https://bugreports.qt.io/browse/QTBUG-17331