我正在阅读fork
函数以及它如何创建新进程。以下程序运行正常并打印here
十六次,但是,我无法理解执行流程:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
int main()
{
int i;
for (i = 0; i < 4; i++) { // line no. 12
fork(); // line no. 13
}
printf("%s\n", "here");
return 0;
}
在我看来,这个程序有两种方式可以被视为:
第一种方法:fork()
总共被召唤四次。如果我用四次调用fork()
函数替换循环,事情似乎已经到位,我理解为什么here
打印2 ^ 4
次。
第二种方法:fork()
完全从调用它的位置产生一个新进程,并且每个子进程都有自己的局部变量。所以,行后没有。 13,这些子进程中的每一个都看到循环结束(}
),然后它们转到第0行。 12.因为,所有这些子进程都有自己的局部变量i
设置为0(可能i
设置为某个垃圾值?),它们都会再次分叉。同样,对于这些子进程,其局部变量i
设置为0.这应该会产生fork bomb。
我肯定错过了我的第二种方法,有人可以帮忙吗?
感谢。
答案 0 :(得分:3)
你的第二种方法是不对的。因为在fork()
之后子进程继承了i
的当前值。它不会在每次调用0
时设置为fork()
,也不会有垃圾值。所以,你的代码不能有叉炸弹。它是一个局部变量的事实是无关紧要的。 fork()
克隆几乎所有内容和子进程都与其父进程相同,除了POSIX手册中指出的某些内容。
为了便于解释,我将循环次数减少到2,并假设所有fork()
次呼叫都成功:
for (i = 0; i < 2; i++) {
fork();
}
printf("%s\n", "here");
1)执行i=0
,fork()
时,现在有两个进程。称他们为P1和P2。
2)现在,每个P1和P2进程继续i = 0循环并将i
增加到1. for
循环条件为真,因此每个进程生成另外两个进程并且总计4.称他们为P1a&amp; P1b和P2a&amp; P2B。所有4个进程现在都有i = 1并将其增加到2(因为它们继续循环)。
3)现在,所有4个进程的值i
为2,并且循环条件在所有进程中都为false,&#34; here&#34;将被打印4次(每个过程一次)。
如果有帮助,您可以将for
循环转换为while
循环以及两个进程从{{1}返回的i
递增的方式可能会变得更清楚:
fork()
答案 1 :(得分:1)
你的第一种方法是对的。
这是一个相当无聊的答案,所以我会给你所有技术细节。
调用fork
时会发生以下几件事:
在函数内声明 的变量存储在堆栈中,因此从相同的值开始,但不共享。
声明外部一个函数(在顶层)的变量不在堆栈中,因此在子/父之间共享。
(其他一些事情有或没有重复;有关详细信息,请参阅man fork
。)
所以,当你运行代码时:
what happens # of processes
1. the parent forks. 2
2. the parent and it's child fork. 4
3. everyone forks 8
4. everyone forks 16
5. everyone prints "here". 16
你最终得到了16个流程,而且这里的“&#39;十六次。
基本上,
if(fork() != 0) {
parent_stuff();
} else {
child_stuff();
}
答案 2 :(得分:0)
使用以下代码,您可以轻松了解fork如何创建变量i的值:
for (i = 0; i < 4; i++) {
printf("%d %s\n", i, "here");
fork();
}
如您所料,子进程复制了父进程的值,因此我们得到0行,其中i = 0; i = 1的2行; i = 2的4行和i = 3的8行。我认为这可以回答您的第二个问题。