2个或更多分叉系统调用如何工作?

这是一个代码,我使用了2个fork()系统调用 – 它是如何工作的?

#include <unistd.h> #include <iostream.h> using namespace std; int main() { cout << "0. I am process " << getpid() << endl; (void) fork(); cout << "1. I am process " << getpid() << endl; (void) fork(); cout << "2. I am process " << getpid() << endl; } 

我得到的输出为:
我正在处理27701
我正在处理25915
我正在处理27701
我正在处理27781
2.我正在处理26170
2.我正在处理27701

这是我使用过3个fork系统调用的下一个程序,我如何得到这样的输出? 如果我手动解决这个代码,那么逻辑是什么?

 #include <unistd.h> #include <iostream> using namespace std; int main() { cout << "0. I am process " << getpid() << endl; (void) fork(); cout << "1. I am process " << getpid() << endl; (void) fork(); cout << "2. I am process " << getpid() << endl; (void) fork(); cout << "3. I am process " << getpid() << endl; } 

在这里我得到的输出为:
我正在处理27116
我正在处理26147
我正在处理27371
我正在处理26147
我正在处理24416
我正在处理27371
我正在处理27508
我正在处理26147
我正在处理27116
我正在处理21406
我正在处理27116
我正在处理27369
我正在处理21406
我正在处理26752
我正在处理27116

Solutions Collecting From Web of "2个或更多分叉系统调用如何工作?"

你的程序是完全错误的。 你不应该忽略fork的结果

阅读高级Linux编程手册和fork(2)手册页(仔细阅读该页面几次)。

典型的代码应该是:

  pid_t pid1 = fork(); if (pid1<0) { perror("fork1 failed"); exit(EXIT_FAILURE); } else if (pid1 == 0) { // you are in the child process } else // pid1>0 { // you are in the parent process } 

同样对于pid_t pid2=fork(); 然后为pid_t pid3=fork(); etc …因此,每次调用fork都应该处理fork的三个结果(失败,即<0 ,子进程==0 ,父进程>0

原则上你有3 3即27种可能性。 但是,你可以尽早处理失败的情况下,留下2 3即8可能性

不要忘记处理fork的失败。 你可能会降低你的进程限制(使用RLIMIT_NPROC或等效的ulimit bash内建setrlimit(2) )来减轻fork失败的测试。

fork()每次调用时都以相同的方式工作。 一个新的进程被创建为当前进程的精确副本,并且都继续执行,就好像它们只是从fork()函数调用返回一样,只是返回值不同。 在你的情况下,你扔掉了返回值,所以他们只是相同的过程。

让我们为你的第一个例子画一幅画。 我刚刚做的一个运行的样本输出(因为您输入的问题的输出是不完整的):

 0. I am process 25597 1. I am process 25597 2. I am process 25597 1. I am process 25598 2. I am process 25599 2. I am process 25598 2. I am process 25600 

您从PID 25597单个进程开始。它打印0行,然后分叉。 这产生了两个过程:

  25597 # prints "0" /\ / \ / \ 25597 25598 # both print "1" 

到现在为止还挺好。 现在这两个新进程再次调用fork() 。 完整的树最终看起来像这样:

  25597 /\ / \ / \ / \ / \ 25597 25598 # both print "1" /\ /\ / \ / \ / \ / \ 25597 25599 25598 25600 # all four print "2" 

不幸的是,25599和25600的实际位置不能从输出中猜出来 – 也可能是相反的。

对于你的3- fork()例子,你只需要做同样的事情,但是它会在图中有另一个层次 – 最后会有8个进程打印“3”行。

只需绘制一棵树,其中每个根节点都是一个fork调用,叶节点就是它后面的代码。

在第一个程序中,你的cout <<“0 …”是父程序,并且在fork调用之后,该行之后的整个程序执行两次。因此两个“1 …”输出行。

现在还有另外一个分叉。 这次有三个进程正在运行(1.你所调用的原始父母,2.它产生的孩子3.孩子本身产生另一个孙子。)
因此3“2 …”输出线。

当一个fork()被调用时,一个子进程被创建并运行。 因此,您在子进程中执行一次以下语句:

 cout << "1. I am process " << getpid() << endl; 

另外,当调用另一个fork时,会创建另一个运行下一个“cout”语句的子进程。 但是,父进程也运行。 这发生在第三个fork()上。

所有这些都发生在第一个fork()的子进程中。 在此之后,第一个分支的父进程也运行以显示您的输出。