Создание рекурсивного дерева процессов с использованием fork () - PullRequest
0 голосов
/ 29 октября 2018

Я пытаюсь создать дерево процессов. На рисунке можно увидеть пример ожидаемого результата при запуске программы с параметром 5.

Когда программа завершает работу, только процессы последнего уровня (листья) должны печатать свой pid.

Когда я запускаю программу с параметром уровня 1, она выводит 1 процесс. Если уровни = 2, то выход = 3 процесса. Уровень = 3, выход = 2 процесса. Уровень = 4, выход = 6 процессов. Уровень = 5, выход = 4 процесса.

Как видите, все нечетные уровни дают правильное количество процессов, а четные - нет. Ожидаемый результат - 1 процесс для уровня 2 и 2 процесса для уровня 4.

enter image description here

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

void startProcess(int level, int max);
void fork_r(int level, int max);

int main(int argc, char *argv[]){
    int n;

    if(argc != 2){
        printf("Wrong number of arguments");
        exit(-1);
    }

    n = atoi(argv[1]);
        if(n <= 0){
        printf("Insert positive integer as argument");
        exit(EXIT_FAILURE);
    }

   fork_r(1, n); //start from level one and go until n

   return 0;
}

void fork_r(int level, int max){
    if(level > max){
         printf("Process: %d \n", getpid()); //if recursion done print pid of leafs
         return;
    }
    if(level % 2 != 0){ 
        startProcess(level, max);
        exit(0); 
    } else {
        startProcess(level, max);
        startProcess(level, max);
        exit(0);
    }
}

void startProcess(int level, int max){
    pid_t pid = fork();
    if(pid == 0){
        fork_r(level + 1, max);
   } else 
        return;
}

1 Ответ

0 голосов
/ 29 октября 2018

Разумная часть, использующая fork(), состоит в том, чтобы никогда не забывать, что при создании нового процесса вы получаете два процесса: одна распространенная ошибка - обрабатывать дочерний случай (if fork() == 0 { child code }) и упускать из виду тот факт, что ребенок будет также выполните код после дочернего кода, если он не разделен должным образом. Что может невольно привести к вилочной бомбе .

Предлагаемый код для fork_r() (действительно рекурсивно)

void fork_r(int me, int max) {
    if (me == max) {
        printf("Level %d, pid %ld\n", me, (long)getpid());
    }
    else {
        if (fork() == 0) {
            fork_r(me+1, max);
        }
        else if (!(me & 1)) {   // Note the 'else'
            fork_r(me+1, max);
        }
    }
}

Приведенный выше код fork() и в родительском проверяет четный уровень, и в этом случае выполняется еще один fork().

...