【问题标题】:fork() within a fork() within a while loopfork() 在 fork() 内 fork() 在 while 循环内
【发布时间】:2015-07-16 03:03:48
【问题描述】:

请考虑在此处查看我的代码。我的计划是我有一个while循环。在那个 while 循环中,我执行了一个 for 语句。在for循环之后,我使用fork。现在我有一个父母和一个child1。在父级内部,我执行了另一个分叉,给了我一个父级和child2。现在我的问题是:

1) 为什么当x=3 时,“fork1 成功”语句会打印两次?

2) 对于x=2x=3 也出现了同样的问题。它说 fork 1 和 fork 2 成功但没有输入child1child2。它跳过了n=waitpid(-1, &status, 0);这一行,然后继续打印n,然后是x--并转到x=1;

3) 对于 x=1,我认为输出确实混淆了,例如为什么在 SENDING 1 和 SENDING 2 之间打印了“child1 pid=4783”。fork 1 也再次打印了两次。

请帮我解决这些问题。我一直在阅读帖子,但似乎看不到类似的问题。我可能错过了什么?太感谢了! 这是我的代码的 sn-p:

while(x>0)
{
    printf("x=%d\n", x);
    for(i=0; i<3; i++)
    {
        printf("SENDING %d\n", i);
    }

    pid1=fork();
    printf("fork1 successful\n");
    if(pid1>0)
    {
        printf("RECEIVING %d\n", i);
        pid2=fork();
        if(pid2>0)
        {
            printf("fork2 successful\n");
            n=waitpid(-1, &status, 0);
            printf("%d\n", n);

            if(n==pid1) //sleep done
            {
                kill(pid2, SIGKILL);
                printf("Child1 ran. Child2 killed.\n\n");
            }

            else if(n==pid2) //scanf received               
            {
                kill(pid1, SIGKILL);
                printf("Child2 ran. Child1 killed.\n\n");
            }
        }    
        else
        {
            printf("child2 pid=%d\n", getpid());            
            scanf("%d", &y);
            exit(1);
        }
    }
    else
    {
        printf("child1 pid=%d\n", getpid());
        sleep(5);
        exit(0);
    }
x--;
}

结果如下:

x=3

SENDING 0

SENDING 1

SENDING 2

fork1 successful

RECEIVING 3

fork1 successful

child1 pid=4781

fork2 successful

child2 pid=4782

4781

Child1 ran. Child2 killed.

x=2

SENDING 0

SENDING 1

SENDING 2

fork1 successful

RECEIVING 3

fork1 successful

fork2 successful

4782

x=1

SENDING 0

SENDING 1

child1 pid=4783

SENDING 2

fork1 successful

RECEIVING 3

child2 pid=4784

fork2 successful

child2 pid=4786

fork1 successful

child1 pid=4785

1

4784

【问题讨论】:

  • 你的问题太多了。让人困惑。前两个问题的答案很简单。 fork 后面有 printf。因此,父母和孩子都会打印它,因此您会看到该行输出了两次。不清楚“没有同时输入 child1 和 child2”是什么意思。输出显示确实如此 - child1 pid=child2 pid= 输出来自子进程。
  • 对不起,我的错。我想说的是,对于 x=2,child1 和 child2 pid 没有打印,这就是我的意思是“没有输入 child1 和 child2”。但我注意到对于 x=1,打印了 4 个子 pid
  • 模糊相关:确保在fork 之前调用fflush,否则如果重定向输出,这将突然以奇怪的方式失败。

标签: c for-loop while-loop fork


【解决方案1】:

我相信您假设n=waitpid(-1, &amp;status, 0) 将暂停,直到其中一个子进程完成。 waitpid 将在任何子进程发生任何更改后返回。如果在打印语句中添加变量“x”,并且还添加一条语句以显示来自waitpid 的状态返回值,您可以看到在x=2 的第二个循环中,触发了waitpid 语句通过前一个循环的进程之一的终止信号。事情在这里变得更加混乱 - 因为进程可能会互相抢占。在您的原始代码中,您可以看到 x=1 出现了两个 child1 进程。

x=3
[3] SENDING 0
[3] SENDING 1
[3] SENDING 2
[3] fork1 successful
[3] RECEIVING 3
[3] fork2 successful
[3] fork1 successful
[3] child1 pid=8166
[3] child2 pid=8167
[3] child1 exiting
[3] process ID 8166 returned status 0.[3] Child1 ran. Child2 killed.

x=2
[2] SENDING 0
[2] SENDING 1
[2] SENDING 2
[2] fork1 successful
[2] RECEIVING 3
[2] fork1 successful
[2] fork2 successful
[2] process ID 8167 returned status 9.x=1
[1] SENDING 0
[1] SENDING 1
[1] SENDING 2
[2] child1 pid=8171
[2] child2 pid=8172
[1] fork1 successful
[1] RECEIVING 3
[1] fork1 successful
[1] child1 pid=8173
[1] fork2 successful
[1] child2 pid=8174
[2] child1 exiting
[1] child1 exiting
[1] process ID 8171 returned status 0

解决此问题的一种方法是检查waitpid 的状态:

do
{
  n=waitpid(-1, &status, 0);
  printf("[%d] process ID %d returned status %d.", x, n, status);
  if (WIFEXITED(status)==0)
     printf("This is NOT an exit status, so I will keep looping....\n");
  else
     printf("\n");

 } while (WIFEXITED(status)==0);

那么我相信你会得到预期的结果:

x=3
[3] SENDING 0
[3] SENDING 1
[3] SENDING 2
[3] fork1 successful
[3] RECEIVING 3
[3] fork2 successful
[3] fork1 successful
[3] child1 pid=8267
[3] child2 pid=8268
[3] child1 exiting
[3] process ID 8267 returned status 0.
[3] Child1 ran. Child2 killed.

x=2
[2] SENDING 0
[2] SENDING 1
[2] SENDING 2
[2] fork1 successful
[2] RECEIVING 3
[2] fork2 successful
[2] process ID 8268 returned status 9.This is NOT an exit status, so I will keep looping....
[2] fork1 successful
[2] child1 pid=8270
[2] child2 pid=8271
[2] child1 exiting
[2] process ID 8270 returned status 0.
[2] Child1 ran. Child2 killed.

x=1
[1] SENDING 0
[1] SENDING 1
[1] SENDING 2
[1] fork1 successful
[1] RECEIVING 3
[1] fork1 successful
[1] child1 pid=8273
[1] fork2 successful
[1] process ID 8271 returned status 9.This is NOT an exit status, so I will keep looping....
[1] child2 pid=8274
[1] child1 exiting
[1] process ID 8273 returned status 0.
[1] Child1 ran. Child2 killed.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 2013-10-24
    • 2015-11-08
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多