【问题标题】:Parent id in fork() and early terminationfork() 中的父 ID 和提前终止
【发布时间】:2017-11-27 01:40:58
【问题描述】:

我正在使用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

【问题讨论】:

  • 您可以在这里获取更多信息:csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html
  • “我知道父进程应该等待它的子进程。”它不会自动您必须致电 wait()waitpid()
  • 你不要等你的孩子有什么要补充的。
  • 我知道,如果您阅读我的问题,您可以详细回答我希望。 @Stargateur
  • 顺便说一句,我总是用你的minimal reproducible example 输出 4 行。而且我不明白这怎么可能少...你能证明你得到这种输出吗?

标签: c parallel-processing fork posix


【解决方案1】:

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

有关更多详细信息,请参阅这两个答案:

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

【讨论】:

    【解决方案2】:

    1) 对于第二个问题,当子进程的父进程在它之前死亡时,子进程被称为Orphan process,在这种情况下,进程 init 成为所有此类的父进程,这就是为什么你得到 1 作为父进程身份证。

    2) 对于第二个问题,一般不会出现这种情况,所以请检查你的fork() 输出值,检查fork() 是否失败。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        发生这种情况的原因是父进程在子进程调用 getppid() 之前退出。这会导致子进程在 init 进程下重新成为父对象。

        根据操作系统的不同,您的结果会有所不同,因为对于在分叉后先安排父级还是子级有不同的规则。

        【讨论】:

          猜你喜欢
          • 2012-02-24
          • 1970-01-01
          • 1970-01-01
          • 2020-01-22
          • 2016-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-04
          相关资源
          最近更新 更多