R 函数 mcfork 只是系统调用 fork 的包装器(顺便说一句,手册页说,这个调用本身就是 clone 的包装器)
我创建了一个简单的 C++ 程序来测试fork 的行为:
#include <stdio.h>
#include <unistd.h>
#include<vector>
int main(int argc, char **argv)
{
printf("--beginning of program\n");
std::vector<std::vector<int> > l(50000, std::vector<int>(50000, 0));
// while (true) {}
int counter = 0;
pid_t pid = fork();
pid = fork();
pid = fork();
if (pid == 0)
{
// child process
int i = 0;
for (; i < 5; ++i)
{
printf("child process: counter=%d\n", ++counter);
}
}
else if (pid > 0)
{
// parent process
int j = 0;
for (; j < 5; ++j)
{
printf("parent process: counter=%d\n", ++counter);
}
}
else
{
// fork failed
printf("fork() failed!\n");
return 1;
}
printf("--end of program--\n");
while (true) {}
return 0;
}
首先,程序在堆上分配了大约 8GB 的数据。
然后,它通过 fork 调用产生 2^2^2 = 8 个孩子并等待被用户杀死,然后进入无限循环以便在任务管理器上轻松发现。
以下是我的观察:
- 要使分叉成功,我的系统上至少需要有 51% 的可用内存,但这包括交换。您可以通过编辑
/proc/sys/vm/overcommit_* proc 文件来更改此设置。
- 正如预期的那样,没有一个子进程占用更多内存,因此这 51% 的空闲内存在整个程序过程中保持空闲,并且所有后续分叉也不会失败。
- 内存在分叉之间共享,因此只有在您杀死最后一个孩子后才会回收。
内存碎片问题
您不应该担心任何与 fork 相关的内存碎片层。 R 的内存碎片在这里不适用,因为 fork 是在虚拟内存上操作的。您不必担心物理内存的碎片,因为几乎所有现代操作系统都使用虚拟内存(因此它们可以使用交换)。唯一可能存在问题的内存碎片是虚拟内存空间的碎片,但 Linux 虚拟内存空间上的 AFAIK 是 2^47,这非常大,几十年来,您在寻找连续区域时应该没有任何问题任何实用的尺寸。
总结:
确保您拥有比物理内存更多的交换空间,并且只要您的计算实际上不需要比 RAM 中更多的内存,您可以mcfork 任意数量。
或者,如果您愿意冒整个系统稳定性(内存不足)的风险,请在 linux 上以 root 身份尝试echo 1 >/proc/sys/vm/overcommit_memory。
或者更好:(更安全)
echo 2 >/proc/sys/vm/overcommit_memory
echo 100 >/proc/sys/vm/overcommit_ratio
您可以在此处阅读有关过度使用的更多信息:https://www.win.tue.nl/~aeb/linux/lk/lk-9.html