Правильный путь к процессу форка - PullRequest
0 голосов
/ 03 сентября 2018

Я пытаюсь отправить запрос на сервер и предварительно каждый раз его разветвлять:

int main(void)
{
    // request send
    fork();
// errx() error handling
    return 0;
}

Это, однако, вызывает только 1 разветвление, а затем происходит сбой программы. Я просматривал некоторые документы в Интернете и не могу понять, что я делаю неправильно и почему он не разветвляется каждый раз, когда он пытается запросить сервер.

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

Ваша главная проблема - путь выполнения. И родительский, и дочерний процессы продолжают errx, что, по-видимому, убивает активный процесс, что означает отсутствие итераций в родительском или дочернем процессах. Вы не проверяете результат fork, который намеренно поможет вам определить, сработала ли функция (а) и (b) текущий процесс является родительским или только что разветвленным дочерним.

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

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

int main()
{
    for (int i=0; i<10; ++i)
    {
        pid_t pid = fork();
        if (pid == 0)
        {
            // handle child process here
            sleep(1);
            return EXIT_SUCCESS;
        }

        if (pid < 0)
        {
            perror("Failed to launch child process");
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("child %d started\n", (int)pid);
            int res = 0;
            pid = wait(&res);
            printf("child %d exited, result = %d\n", (int)pid, WEXITSTATUS(res));
        }

    }
    return EXIT_SUCCESS;
}

Пример вывода

child 72916 started
child 72916 exited, result = 0
child 72917 started
child 72917 exited, result = 0
child 72919 started
child 72919 exited, result = 0
child 72920 started
child 72920 exited, result = 0
child 72921 started
child 72921 exited, result = 0
child 72923 started
child 72923 exited, result = 0
child 72924 started
child 72924 exited, result = 0
child 72925 started
child 72925 exited, result = 0
child 72926 started
child 72926 exited, result = 0
child 72927 started
child 72927 exited, result = 0

Партии мониторинга

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

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

int main()
{
    for (int i=0; i<3; ++i)
    {
        // batch launch loop
        int n_children = 3;
        for (int j=0; j<3; ++j)
        {
            pid_t pid = fork();
            if (pid == 0)
            {
                // handle child process here
                sleep(1);
                return EXIT_SUCCESS;
            }
            else if (pid < 0)
            {
                perror("Failed to launch child process");
                --n_children;
            }
            else
            {
                printf("child %d started\n", (int)pid);
            }
        }

        // batch wait loop
        for (int j=0; j<n_children; ++j)
        {
            int res;
            pid_t pid = wait(&res);
            printf("child %d exited, result = %d\n", (int)pid, WEXITSTATUS(res));
        }
    }
    return EXIT_SUCCESS;
}

Пример вывода

child 73190 started
child 73191 started
child 73192 started
child 73190 exited, result = 0
child 73191 exited, result = 0
child 73192 exited, result = 0
child 73193 started
child 73194 started
child 73195 started
child 73194 exited, result = 0
child 73193 exited, result = 0
child 73195 exited, result = 0
child 73196 started
child 73197 started
child 73198 started
child 73196 exited, result = 0
child 73197 exited, result = 0
child 73198 exited, result = 0

Надеюсь, вы найдете это полезным.

0 голосов
/ 03 сентября 2018

Необходимо помнить, что и основной (первый) процесс, и дочерний (второй) будут выполнять один и тот же код, а именно вызов функции errx. Обычно это делается с помощью проверки if / else на возвращаемое значение fork. Это было бы что-то вроде этого:

if (fork() == 0) {
    // you are in the child thread here
}
else {
    // and here you are in the parent
}

и вы разделите свою логику между двумя потоками. Если нет, то оба потока будут выполнять один и тот же код до тех пор, пока не прекратят выполнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...