【问题标题】:Trouble understanding fork() output无法理解 fork() 输出
【发布时间】:2016-12-07 13:59:50
【问题描述】:

假设有一个PID = 1 的进程,它运行以下代码:

int a = fork();
int b = fork();
printf(“a: %d, b: %d\n”, a, b); 

让我们进一步假设新的PIDs 将被一一给出,所以第二个给出的PID 将是2,然后是3 等等。

可能的输出是:

a:2, b:3
a:2, b:0
a:0, b:4
a:0, b:0

我在尝试理解上述代码的输出时遇到了一些麻烦,尤其是为什么a:0, b:4a:2, b:3

【问题讨论】:

    标签: c fork pid


    【解决方案1】:

    你知道的

    返回值是子节点中的零和父节点中子节点的进程ID号,或者错误时为-1。

    那么,让我们一步一步看看这里发生了什么。

    fork() 被调用时,它会创建一个ID 为n 的新子代,然后在子代0 和父代n 中返回。

    假设我们的进程为 pid 1,当第一个 fork() 被调用时,它会创建一个 pid 2 的进程,然后返回一个 a 值。 a 在进程 2(子进程)中将具有值 0,在进程 1(父进程)中将具有值 2

    然后每个进程都会调用fork(),并将返回值赋给父进程中的b。在孩子中,b 将具有值0

    无论如何,我认为这个架构会简化理解:

    主要开始:

    |
    |
    int a = fork(); // It creates a new process, and the old one continues going
    |
    |-------------------------|
    a = 2; /* Parent */       a = 0; // Child
    |                         |
    |                         |
    int b = fork();           int b = fork(); // Each one create a new process
    |                         |
    |                         |-----------------------------|
    |                         /* Child -> Parent */         // Child -> Child
    |                         a = 0; b = 4;                 a = 0; b = 0
    |
    |
    |
    |
    |-----------------------------|
    /* Parent -> Parent */        // Parent -> Child
    a = 2; b = 3;                 a = 2, b = 0; 
    

    【讨论】:

      【解决方案2】:

      我什至不想回答你的问题。它更多地是关于显示常用的模式。如果 cmets 中只有正确的代码格式,它可能是一个注释。

      fork() 的基本构造是:

      if (int PID = fork() == 0 ) {
          //it's a child process
      } else {
          //it's a parent process
      }
      

      使用简单

      int PID1 = fork();
      int PID2 = fork();
      

      风险很大,因为您几乎肯定会收到Race condition

      【讨论】:

        【解决方案3】:
        Original process:
        forks child A, and child B
        prints `a:2, b:3`
        
            child A process:
            forks child BB
            prints `a:0, b:4`
        
                child BB proess:
                forks nothing
                prints `a:0, b:0`
        
            child B process:
            forks nothing
            prints `a:2, b:0`
        

        由于您没有使用任何waitwaitpid,因此它们可以按任何顺序出现。

        【讨论】:

          【解决方案4】:

          fork 之后,您可以在父亲中(fork 返回孩子的 PID)或在孩子中(fork 返回0)。

          在第一次调用fork 后,您将拥有两个进程:父进程(在您的示例中为a = 2)和子进程(a = 0)。

          两者都会分叉,父亲 (a = 2) 将生一个孩子 (b = 0) 和一个新父亲 (b = 3)。孩子 (a = 0) 将给一个新孩子 (b = 0),它将成为其父亲 (b = 4)。

          你可能的输出是:

          a:2, b:3 -> father and father
          a:2, b:0 -> father and child
          a:0, b:4 -> child and father
          a:0, b:0 -> child and child
          

          【讨论】:

            【解决方案5】:

            第一次分叉之前:

            PID 1 (father)
            a = (not in scope yet)
            b = (not in scope yet)
            

            第一次分叉后:

            PID 1 (father)
            a = 2
            b = (not in scope yet)
            
            PID 2 (child of 1)
            a = 0
            b = (not in scope yet)
            

            第二次分叉后:

            PID 1 (father)
            a = 2
            b = 3
            
            PID 2 (child of 1)
            a = 0
            b = 4
            
            PID 3 (child of 1)
            a = 2
            b = 0
            
            PID 4 (child of 2)
            a = 0
            b = 0
            

            【讨论】:

            • 谢谢。这可能是一个简单的,但为什么在PID 3a = 2a怎么还剩下2
            • 因为 3 是 1 的子代,因此在第二次调用 fork 之前是 1 的完整克隆,包括 a 的值。
            猜你喜欢
            • 2012-04-29
            • 1970-01-01
            • 2023-03-25
            • 1970-01-01
            • 1970-01-01
            • 2021-05-30
            • 2021-03-08
            • 2013-12-23
            • 2014-09-19
            相关资源
            最近更新 更多