Код Fork () не работает должным образом - Создание иерархии - PullRequest
0 голосов
/ 16 октября 2019

Добрый день.

В настоящее время я работаю над программой на C, которая принимает один и только один параметр, который определяет количество создаваемых «дочерних поколений» (собственный отец уже считается 1). Системные вызовы "wait ()" не должны использоваться для этого упражнения (версия с вызовами "wait" работает точно так же, как и ожидалось).

Например, программа $ call 4 должна сгенерировать иерархию, подобную этой: Процесс A создает B Процесс B создает C Процесс C создает D

Печатные сообщения не важны, поскольку они простоориентируется на задачу. В следующем коде (который работает точно так, как я хочу при вызове wait ()) говорится, что все дочерние процессы происходят от одного и того же отца, что я не понимаю, почему это происходит.

#include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>

    int main(int argc, char *argv[]) {
    int counter; pid_t result; int i;

    /*
    We are going to create as many processes as indicated in argv[1] taking into account that the main father already counts as 1!
    */
    if (argc > 2 || argc == 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
    int lim = atoi(argv[1]);


    //We eliminate the impossible cases
    if (lim < 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}


    if (lim == 1) {puts("The father himself constitutes a process all by his own, therefore:\n");
    printf("Process%d, I'm %d and my father: %d\n", counter, getpid(), getppid());
     }
    else {
        for (i = 0; i < lim; i++) {
            result = fork();
            if (result < 0) {
                printf("Call%d \n", counter); perror("Has failed!");
                exit(-1);
            }
            else if (result) {
                break; //Father process
            }
            else {
                counter++;    //Child processes increment the counter
                printf("Process%d, I am %d and my father: %d\n", counter, getpid(), getppid());
            }
        }
    }

Иерархия, сгенерированная приведенным выше кодом, не та, которую я ожидал ...

Вся помощь очень ценится. Спасибо

Ответы [ 2 ]

1 голос
/ 16 октября 2019

В следующем коде (который работает точно так, как я хочу при вызове wait ()) говорится, что все дочерние процессы происходят от одного и того же отца, что я не понимаю, почему это происходит.

Я не вижу этого в своих тестах, и у меня нет никаких оснований ожидать, что это действительно так. ОДНАКО, это может показаться подходящим для вас, если вы видите, что некоторые или все дочерние процессы сообщают о процессе 1 в качестве их родителя. Это произойдет, если их первоначальный родительский объект завершится до того, как будет обработан вызов ребенка getppid(). Процессы, потерянные таким образом, наследуют процесс 1 как своего родителя. Если родительский wait() s для дочернего элемента завершается первым, то это не может произойти, но если вместо этого родительский элемент завершает работу очень скоро после разветвления дочернего элемента, тогда этот результат вполне правдоподобен.

Вот вариант вашего цикла, которыйбудет сообщать исходный идентификатор родительского процесса в каждом случае:

    pid_t my_pid = getpid();

    for (i = 0; i < lim; i++) {
        result = fork();
        if (result < 0) {
            printf("Call%d \n", counter); perror("Has failed!");
            exit(-1);
        } else if (result) {
            break; //Father process
        } else {
            pid_t ppid = my_pid;  // inherited from the parent
            my_pid = getpid();
            counter++;    //Child processes increment the counter
            printf("Process%d, I am %d and my father: %d\n", counter, (int) my_pid, (int) ppid);
        }
    }
0 голосов
/ 16 октября 2019

Вам не хватает критически важного вызова функции.

    for (i = 0; i < lim; i++) {
        fflush(stdout);             // <============== here
        result = fork();

Без него ваш fork дублирует буфер stdout родителя в дочерний процесс. Вот почему вы видите, что вывод родительского процесса повторяется несколько раз - его дочерние элементы и внуки наследуют буфер вывода.

Демонстрационная версия (с фиксированным форматированием для вашего удобства чтения).

...