父进程在尝试分叉子进程时失败并且errno = 12(内存不足)。父进程在Linux 3.0内核上运行 - SLES 11.在分叉子进程时,父进程已经占用了大约70%的RAM(180GB / 256GB)。这个问题有解决办法吗?
应用程序是用C ++编写的,用g ++ 4.6.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了解更多信息。
如果您fork
仅运行gdb
来显示回溯,请考虑更简单的替代方案,例如recent GCC's libbacktrace或Wolf'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