进程 - child 还是 grandchild?

Process - child or grandchild?

我有这部分代码,运行顺利,但我不知道创建的第二个进程是第一个 child 的大 child,还是只是 child过程。这是:

if (fork() != 0)
    parent(array,N);
else {
    child1(array,N);
    if(fork() != 0) 
        child2(array,N);
}

同上:

if (fork() != 0)
    parent(array,N);
else {
    child1(array,N);
}

if (fork() == 0)
    child2(array,N);

因为我得到了相同的结果。该程序有一个数组,parent 计算数组的第一个 1/3 的最大值,第一个 child 第二个 1/3 和第二个 child 第三个。 Parent 从 children 的管道中获取结果并打印出来。对于我上面展示的 2 个版本运行相同。

#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

int pfd1[2],pfd2[2]; // pfd[1] gia to prwto paidi , pfd[2] gia to deutero paidi

void parent(int array[],int N) {



    int i;
    int max_p;
    int child1_max,child2_max;        //auto pou 8a steilei

    max_p=array[0];      // <============================================================================

    close(pfd1[1]); //no writing by the parent
    close(pfd2[1]); //no writing by the parent

    for(i=0;i<N/3;i++) {

        if(array[i]>max_p) {
            max_p=array[i];
        }
    }

    waitpid(-1, NULL, 0);   /* Wait my child process */

    read(pfd1[0],&child1_max,sizeof(int)); //get 1st child's max_c
    close(pfd1[0]);

    read(pfd2[0],&child2_max,sizeof(int)); //get 1st child's max_c
    close(pfd2[0]);

    printf("1st child_max is %d\n",child1_max); 
    printf("2nd child_max is %d\n",child2_max);
    printf("parents max is %d\n",max_p);

    /*if(max_p>child_max) {
        printf("max is %d (was in parent)\n",max_p);
        printf("max of child is %d\n",child_max);
    }else {
        printf("max is %d (was in child)\n",child_max);
        printf("max of parent is %d\n",max_p);
    }*/


}


void child1(int array[],int N) {
    int i;

    int max_c=array[N/2];    // <============================================================================

    close(pfd1[0]); // No reading by child

    for(i=N/3;i<(2*N)/3;i++) {

        if(array[i]>max_c) {
            max_c=array[i];
        }
    }

    write(pfd1[1],&max_c,sizeof(int));
    close(pfd1[1]);
}

void child2(int array[],int N) {
    int i;

    int max_c=array[(2*N)/3];  // <============================================================================

    close(pfd2[0]); // No reading by child


    for(i=(2*N)/3;i<N;i++) {

        if(array[i]>max_c) {
            max_c=array[i];
        }
    }

    write(pfd2[1],&max_c,sizeof(int));
    close(pfd2[1]); 



}

int main(void) {

    int array[]={111,1222,10,392,3211,3,2,50,8};
    int N=sizeof(array)/sizeof(int);

    //printf("\n %d \n",N);

    if (pipe(pfd1) < 0)
    {
        perror("pipe()");
        exit(1);
    }

    if (pipe(pfd2) < 0)
    {
        perror("pipe()");
        exit(1);
    }

    if (fork() != 0)
        parent(array,N);

    else {
        child1(array,N);

        //if(fork() != 0) 
        //  child2(array,N);
    }

    if (fork() == 0)
        child2(array,N);

    return 0;

}

在第一个例子中我们有以下过程:

Parent
    parent()
    Child
        child1()
        child2()
        Grandchild
            Doesn't so anything

因为第二个fork()是在子进程中完成的。然后当结果为非零时它调用 child2(),这意味着它是调用 fork() 的同一个进程。由于第二个 if 没有 else 块,孙子没有 运行 任何代码(实际上,它会 运行 你发布的所有代码之后的代码)。

第二个例子如下:

Parent
    parent()
    Child 1
        child1()
    Child 2
        child2()

在这种情况下,第二个fork()在原来的流程中执行。

此外,如果 child1() 不退出进程,子进程 1 将在第一个 if/else 完成后继续执行,因此它 也会 执行第二个fork()。然后你会得到以下内容:

Parent
    parent()
    Child 1
        child1()
        Grandchild
            child2()
    Child 2
        child2()

首先,它们是不一样的。在第二段代码中,从第一个 if (fork() != 0) 创建的 parent 和 child 都将调用第二个 if (fork() == 0) (创建另外两个 child 进程,其中一个是一个伟大的 child)。 在第一段代码中,只有if (fork() != 0)创建的child会调用第二个if(fork() != 0)。在这两个例子中都有一个宏大的child过程。

此外,在第一段代码中,您将 child2(array,N) 称为 parent(嗯,作为第一个 child)。通过这样做,你最终会无缘无故地分叉。如果您希望 child 调用 child2(array,N)(从而成为真正的 grandchild),您应该执行 if (fork() == 0)。现在,grandchild 进程刚刚退出。

这是一棵树来展示叉子。 第一段代码的树。请注意,树上的 eversplit 代表一个 fork 调用。我们往上走就是child进程,往下走就是fork的parent进程。我在树中添加了延迟以显示等待。

第二段代码的树:

您得到相同结果的原因是因为 parent 进程调用的第二个 child2 发生在您打印结果之后。

此外,在 parent 中,您只等待第一个 child,但您使用第二个 child 的结果。您还应该向 child1.

添加一些等待逻辑

我建议你使用以下

if (fork() != 0)
    parent(array,N);
else {
    child1(array,N);
    if(fork() == 0) 
        child2(array,N);
}

这有以下树。

这里,child2被称为grandchild进程。