Процесс - ребенок или внук? - PullRequest
0 голосов
/ 13 января 2020

У меня есть эта часть моего кода, она работает гладко, но я не могу понять, является ли второй созданный процесс внуком первого дочернего процесса или просто дочерним процессом. Это:

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);

потому что я получаю те же результаты. У программы есть массив, а родительский элемент вычисляет максимальное значение для 1/3 массива, 1-го дочернего элемента, второго 1/3 и 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;

}

Ответы [ 2 ]

2 голосов
/ 13 января 2020

Во-первых, это не одно и то же. Во втором фрагменте кода родитель и потомок, созданные из первого if (fork() != 0), будут вызывать второй if (fork() == 0) (создавая еще два дочерних процесса, один из которых будет внуком). В первом фрагменте кода только дочерний элемент, созданный if (fork() != 0), будет вызывать второй if(fork() != 0). В обоих примерах есть процесс внука.

Кроме того, в первом фрагменте кода вы вызываете child2(array,N) в качестве родителя (ну, как первого потомка). Делая это, вы в конечном итоге разветвляетесь без причины. Вы должны сделать if (fork() == 0), если хотите, чтобы ребенок позвонил child2(array,N) (и, таким образом, был истинным внуком). Прямо сейчас процесс внука только что завершился.

Вот дерево, чтобы показать вилки. Дерево для первого куска кода. Обратите внимание, что разделение evert на дерево представляет собой вызов fork. Когда мы go вверх, мы являемся дочерним процессом, а когда go вниз, мы являемся родителем разветвления. Я добавил задержки в дереве, чтобы показать ожидания. enter image description here

Дерево для второго фрагмента кода: enter image description here

Причина, по которой вы получаете те же результаты, заключается в том, что второй child2, который вызывается родительским процессом, происходит после того, как вы напечатаете результаты.

Кроме того, в parent вы ожидаете только первого дочернего элемента, но используете результаты второго дочернего элемента. Вам также следует добавить некоторые логики ожидания c к child1.

. Я бы предложил вам использовать следующее

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

Это дерево имеет следующее. enter image description here

Здесь child2 называется процессом внука.

2 голосов
/ 13 января 2020

В первом примере у нас есть следующие процессы:

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()
...