fork():创建的子进程数

时间:2018-12-09 11:01:50

标签: c fork

dataType: "html"

我认为它应该总共生成6个子进程。但事实并非如此。为什么

1 个答案:

答案 0 :(得分:3)

说明

fork()创建一个 duplicate 进程,该进程将从与父级并行调用的任何地方继续运行代码。在父fork()中返回子PID,在子fork中返回零-不同于新进程是相同的,但它们是彼此的副本-在一个变量中设置变量不会影响另一个。

通常在fork()之后,您检查返回的代码,以查看程序的此副本是孩子还是父母,并采取相应的行动。

更正的代码

因此,如果您打算创建6个子进程(加上一个父进程),则应该执行以下操作:

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
int main() 
{ 

  printf("Hello from parent, my PID is %d\n", getpid());
  for(int i=0;i<6;i++)
  {  
    int pid = fork(); 
    if (pid == 0)
    {
       printf("Hello from child, my PID is %d\n", getpid());
       return 0;
    }
    printf("Parent created child with PID=%d\n", pid);
  }    
return 0; 
} 

并且我系统上的输出是:

Hello from parent, my PID is 26354
Parent created child with PID=26355
Hello from child, my PID is 26355
Parent created child with PID=26356
Parent created child with PID=26357
Parent created child with PID=26358
Hello from child, my PID is 26356
Parent created child with PID=26359
Parent created child with PID=26360
Hello from child, my PID is 26357
Hello from child, my PID is 26358
Hello from child, my PID is 26359
Hello from child, my PID is 26360

请注意,每个孩子都打印出Hello from child...消息,然后通过returnmain()中退出而退出。

错误

  • 您的代码会检查错误,因此生成的子代不会只是退出-他们继续创建自己的子代,而子代也会这样做。

    • 您应该每次都分配pid = fork(),而不仅仅是第一次。

    • 如果您的孩子做完了,建议通过调用return使其立即退出,而不是让它继续循环遍历程序并将其部分包装在if (pid==0)检查中-这可能会导致进一步的错误

    • 您的父母创建了第一个孩子(在循环之前)并收到非零的pid,因此它仍会经历后续的循环,但不执行其他任何操作-第一个孩子会完成所有工作。

  • 此外,每次调用fork\n时,fork()都会打印两次,因为父母和孩子都在每个孩子之后(首先是“循环前”的孩子除外)立即进行打印已创建-可能不是您想要的。

代码分析

让我们看看代码的作用。

我将任意编号进程,进程#0是原始父进程。

int pid =  fork(); 

进程#0创建进程#1。在子级(#1)pid = 0中,父级(#0)非零。

因为以下代码检查pid0

if(pid == 0)
{
    fork();
    printf("fork\n");
} 

...进程#0循环5次,但不执行任何操作,不打印任何内容,最终退出。

因为pid不再被写入并且不被检查,所以对于进程#1和所有后续进程,此循环如下所示:

for(int i=0;i<5;i++)
{  
      fork();
      printf("fork\n");
}    
return 0; 

以下是并行发生的,顺序是任意的:

  • 现在,进程#1创建五个孩子-#2,#3,#4,#5,#6,每次打印出fork\n,并最终退出。

  • 进程#2在{#1}之前的i=0处以printf开始创建进程#1,因此它打印出fork\n并继续打印出消息4更多次并创建自己的4个子级(#7,#8,#9,#10),并最终退出

  • 进程#3从{1}到i=1之前的printf开始创建进程#1,因此它打印出fork\n,并继续创建3个子进程。自己打印3次(#11,#12,#13)并最终退出

  • 进程#4创建2个进程(#14,#15),打印3条消息

  • Process#5创建1个进程(#16),打印2条消息
  • 进程#6与i=4一起保留,因此它会打印出一条消息并退出。

  • 进程#7(由第二个孩子创建)在与进程#3相同的情况下被保留,因此它将消息打印4次并创建自己的3个孩子...

...到此为止,我可能会停下来,您应该已经知道运行的方向。

这是我在其中添加一些日志记录之后的程序输出。我还对输出进行了一点排序-因为所有这些并行发生,否则很难跟踪:

Process 27939 is the original parent
Process 27939 created process 27940 <--- this is the 'out-of-loop' child
Process 27939 finished executing
Process 27940 created process 27942
Process 27940: fork
Process 27940 created process 27943
Process 27940: fork
Process 27940 created process 27944
Process 27940: fork
Process 27940 created process 27945
Process 27940: fork
Process 27940 created process 27946
Process 27940: fork
Process 27940 finished executing
Process 27942: fork
Process 27942 created process 27954
Process 27942: fork
Process 27942 created process 27955
Process 27942: fork
Process 27942 created process 27956
Process 27942: fork
Process 27942 created process 27957
Process 27942: fork
Process 27942 finished executing
Process 27943: fork
Process 27943 created process 27958
Process 27943: fork
Process 27943 created process 27959
Process 27943: fork
Process 27943 created process 27960
Process 27943: fork
Process 27943 finished executing
Process 27944: fork
Process 27944 created process 27961
Process 27944: fork
Process 27944 created process 27962
Process 27944: fork
Process 27944 finished executing
Process 27945: fork
Process 27945 created process 27963
Process 27945: fork
Process 27945 finished executing
Process 27946: fork
Process 27946 finished executing
Process 27954: fork
Process 27954 created process 27970
Process 27954: fork
Process 27954 created process 27971
Process 27954: fork
Process 27954 created process 27972
Process 27954: fork
Process 27954 finished executing
Process 27955: fork
Process 27955 created process 27978
Process 27955: fork
Process 27955 created process 27979
Process 27955: fork
Process 27955 finished executing
Process 27956: fork
Process 27956 created process 27981
Process 27956: fork
Process 27956 finished executing
Process 27957: fork
Process 27957 finished executing
Process 27958: fork
Process 27958 created process 27980
Process 27958: fork
Process 27958 created process 27982
Process 27958: fork
Process 27958 finished executing
Process 27959: fork
Process 27959 created process 27983
Process 27959: fork
Process 27959 finished executing
Process 27960: fork
Process 27960 finished executing
Process 27961: fork
Process 27961 created process 27984
Process 27961: fork
Process 27961 finished executing
Process 27962: fork
Process 27962 finished executing
Process 27963: fork
Process 27963 finished executing
Process 27970: fork
Process 27970 created process 28002
Process 27970: fork
Process 27970 created process 28003
Process 27970: fork
Process 27970 finished executing
Process 27971: fork
Process 27971 created process 28004
Process 27971: fork
Process 27971 finished executing
Process 27972: fork
Process 27972 finished executing
Process 27978: fork
Process 27978 created process 28006
Process 27978: fork
Process 27978 finished executing
Process 27979: fork
Process 27979 finished executing
Process 27980: fork
Process 27980 created process 28008
Process 27980: fork
Process 27980 finished executing
Process 27981: fork
Process 27981 finished executing
Process 27982: fork
Process 27982 finished executing
Process 27983: fork
Process 27983 finished executing
Process 27984: fork
Process 27984 finished executing
Process 28002: fork
Process 28002 created process 28043
Process 28002: fork
Process 28002 finished executing
Process 28003: fork
Process 28003 finished executing
Process 28004: fork
Process 28004 finished executing
Process 28006: fork
Process 28006 finished executing
Process 28008: fork
Process 28008 finished executing
Process 28043: fork
Process 28043 finished executing