fork()中的父ID和提前终止

时间:2017-06-23 12:57:49

标签: c parallel-processing fork posix

我使用fork()练习并行编程。我希望每个进程的父ID都是前进程的id,但在我的输出中显示相同的id。为什么?第二个问题是关于终止。有时输出显示所有进程,有时只有两个或三个,有时只有一个。为什么?我知道父进程应该等待其子进程,但是如果不是在我的问题中那么。我的困惑是,当fork()被调用时,两个进程都是在不知道它们的命令的情况下执行的,它们不是吗?也许父进程终止它自己的执行。 但它的孩子可以继续跑步到其余的节目或终止或其他什么? (因为它可以在输出上看到并不总是终止,也不总是完全正确)我不理解只显示一个但有时两个或三个或不是全部的输出。 我希望我能解释我的问题。貌似,我无法做到。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main (int argc, char *argv[]) {
   pid_t childpid = 0;
   int i;

   for (i = 0; i < 3; i++)
      if (childpid = fork())
         break;

   fprintf(stderr, "i:%d  process ID:%ld  parent ID:%ld  child ID:%ld\n",
           i, (long)getpid(), (long)getppid(), (long)childpid);
   return 0;
}

输出(一个或多个):

i:0  process ID:2783  parent ID:1954  child ID:2784
i:1  process ID:2784  parent ID:1  child ID:2785
i:2  process ID:2785  parent ID:1  child ID:2786
i:3  process ID:2786  parent ID:1  child ID:0

or
//how??
i:0  process ID:3016  parent ID:1954  child ID:3017  
i:1  process ID:3017  parent ID:1  child ID:3018
i:2  process ID:3018  parent ID:1  child ID:3019

or
//how??
i:0  process ID:4079  parent ID:1954  child ID:4080
i:1  process ID:4080  parent ID:1  child ID:4081

or
//how??
i:0  process ID:3038  parent ID:1954  child ID:3039

预期产出:

i:0  process ID:2783  parent ID:1954  child ID:2784
i:1  process ID:2784  parent ID:2783  child ID:2785
i:2  process ID:2785  parent ID:2784  child ID:2786
i:3  process ID:2786  parent ID:2785  child ID:0

enter image description here

4 个答案:

答案 0 :(得分:10)

您的输出是非确定性的,因为它取决于操作系统调度程序。 你的父母在分叉后比孩子开始时更快离开因此他们得到1作为父母。

有关其他详细信息,请参阅以下两个答案:

  1. https://stackoverflow.com/a/395883/8199273
  2. https://stackoverflow.com/a/23697850/8199273

答案 1 :(得分:1)

1)对于第二个问题,当子进程的父进程在它之前死亡时,子进程被称为<div class="vertical-menu"> <ul id="menu-v" class="main"> <li><a href="#">BIZ OPS -> </a> <ul class="menu"> <li><a href="#">UPLOAD DATA -></a> <ul class="sub-menu"> <li><a href="x1.jsp">UPLOAD x1</a></li> <li><a href="x2.jsp">UPLOAD x2</a></li> <li><a href="x3.jsp">UPLOAD x3</a></li> </ul> </li> <!-- <li><a href="worklist.jsp">WORK LIST</a></li> --> <li><a href="#">IOT -></a> <ul class="sub-menu"> <li><a href="europe.jsp">EUROPE</a></li> <li><a href="apac.jsp">APAC</a></li> <li><a href="ag.jsp">AG</a></li> <li><a href="internalt.jsp">INTERNAL MOVEMENT</a></li> <li><a href="supportiotworklist.jsp">SUPPORT</a></li> </ul> </li> </ul> </li> <li><a href="#">GENERATE REPORTS-> </a> <ul class="sub"> <li><a href="downloadexcel.jsp">x1 REPORT</a></li> <li><a href="downloadhc.jsp">x2 REPORT</a></li> <li><a href="error.jsp">x3 REPORT</a></li> </ul> </li> <li><a href="#">COST CASE -></a> <ul class="sub"> <li><a href="index1.jsp">ADD CCN/PCR</a></li> <li><a href="viewcostcase.jsp">DEBAND COST CASE</a></li> <li><a href="cirelease.jsp">CI RELEASE</a></li> <li><a href="simplecc.jsp">VIEW COST CASE</a></li> <li><a href="IotCostCaseView.jsp">IOT COST CASE VEIW & EDIT</a></li> </ul> </li> <li><a href="#">HIRE EMPLOYEE -></a> <ul class="sub"> <li><a href="#">GRB -></a> <ul class="sub"> <li><a href="int.jsp">INTERNAL HIRE</a></li> <li><a href="ext.jsp">EXTERNAL HIRE</a></li> </ul> </li> <li><a href="#">PROMOTIONS -></a> <ul class="sub"> <li><a href="promolist.jsp">PROMOTIONS WORKLIST</a></li> </ul> </li> </ul> </li> <li><a href="#">WORK LIST -></a> <ul class="sub"> <li><a href="GrbPage.jsp">GRB WORKLIST</a></li> <li><a href="CcnPcrWorklist.jsp">CCN/PCR WORKLIST</a></li> <li><a href="DebandWorklist.jsp">DEBAND WORKLIST</a></li> <li><a href="LowUtemForm.jsp">LOW UTE WORKLIST</a></li> <li><a href="nvp.jsp">NEGATIVE VACANT POSITION WL</a></li> </ul> </li> <li><a href="GrbList">GRB STATUS</a></li> <li><a href="#">USER MANAGEMENT</a></li> </ul> </div>,在这种情况下,进程init成为所有这样的父进程,这就是为什么你得到1作为父母身份。

2)对于第二个问题,通常不应该这样,所以请检查Orphan process输出值,检查fork()是否失败。

答案 2 :(得分:0)

在fork执行的行中,子进程被创建,子进程与父进程相同,在你的代码中父进程在打印后终止并且子进程继续循环并启动另一个子进程(直到我成为3),本身现在是父进程执行print语句。我试着在下面解释一下:

     parent      child
     -----------------------------------------------
prints(i=0)     parent        child
     -----------------------------------------------
            prints(i=1)       parent           child
     -----------------------------------------------      
                              prints(i=2)      Loop Terminates(fork dont get executed)
                                               prints(i=3)

答案 3 :(得分:0)

发生这种情况的原因是父进程在子进程中的getppid()调用之前退出。这会导致孩子在初始化过程中重新成为父母。

根据操作系统的不同,您的结果会有所不同,因为在首先安排分叉后是否安排父母或子女有不同的规则。