Как я могу перечислить все дочерние пиды, прежде чем передать им контроль? - PullRequest
0 голосов
/ 23 января 2019

У меня есть задание, в котором профессор просит родительский процесс напечатать идентификатор процесса каждого дочернего процесса перед передачей управления дочернему процессу.

Я пытался сделать что-то вроде этого:

pid_t cpids[5]; //I want to create 5 child processes
int n = 0;

do {
    cpids[n++] = fork();
} while(cpids[n] > 0 && n < 5) ; //This doesn't fork 5 times

//print all the child pids
printf("The child processes are: %d, %d, %d, %d, %d\n", cpids[0]..);
//(I know this would be printed multiple times, I'm just trying to explain what I need)

//then after printing the ids, tell child processes what to do
for(int i = 0; i < 5; i++) {

    //error
    if(cpids[i] < 0) {
        printf("There was an error with fork()\n");
        exit(1);
    }

    //child process
    else if(cpids[i] == 0) {
    //...reads from pipe sent from parent process
    }

    //parent process
    //sends message through pipe to child process
    //waits for child to terminate
}

Так что это определенно не сработало :).Есть ли более простой способ разветвить процессы, не давая сразу инструкции?Спасибо!

// ОБНОВЛЕНИЕ

Итак, я знаю, что неправильно делаю fork ().Это был мой оригинальный код:

for(int i = 0; i < 5; i++) {
    //error
    if((pid = fork()) < 0) {
        printf("There was an error with fork()\n");
        exit(1);
    }

    //child process
    else if(pid == 0) {
        pid = getpid();
        close(fd[i][1]);

        //read starting position from parent process
        len = read(fd[i][0], &fpos, sizeof(fpos));

        if(len > 0) {
            doChild(numArray, fpos, i);
        }

        printf("id: %d\n", pid);
        _exit(1);
    } 

    //parent process
    else {
        close(fd[i][0]);
        fpos = (SIZE/NUM_CHILD) * i;
        write(fd[i][1], &fpos, sizeof(fpos));

        if ( waitpid(-getpid(), &status, 0) != -1 ) {
            if ( WIFEXITED(status) ) {
                int returned = WEXITSTATUS(status);
                printf("child id: %d ended with status %d\n\n", pid, returned);
            }
        }

        else {
            perror("waitpid() failed");
            exit(EXIT_FAILURE);
        }
    }

}

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

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Я действительно не хочу выполнять ваше задание за вас, но я бы предложил начать с чего-то похожего на это:

void child_func(int readfd) {
    // read from readfd and do whatever
}

void do_fork(pid_t *childpid, int *pipefd) {
    int pipefds[2];
    pid_t pid;
    pipe(pipefds, 0);
    if ((pid = fork()) == 0) {
        child_func(pipefds[0]);
        exit(0);
    } else {
        *childpid = pid;
        *pipefd = pipefds[1];
    }
}

int main() {
    int i;
    pid_t children[5];
    int pipes[5];
    for (i = 0; i < 5; ++i) {
        do_fork(&children[i], &pipes[i]);
    }
    // whatever
    return 0;
}

Если ваш child_func читает из файлового дескриптора в начале, он будетблокировать, пока родительский элемент не записывает остальные 5 дескрипторов.Это дало бы вам возможность распечатать пид или что-то еще, а затем сказать им, что делать.Посмотрите на страницы руководства для "pipe" и "fork", если вы не понимаете это полностью.Надеюсь, этого достаточно, чтобы вы начали.

0 голосов
/ 23 января 2019

Вы, похоже, полностью упускаете точку fork. Это очень особенная функция - она ​​возвращает либо 0, либо неотрицательное целое число, либо -1. Первое, что вам нужно сделать после разветвления, это проверить возвращаемое значение.

Если это не отрицательно, это означает, что вы исполняете в родителе, и вы можете продолжить свою родительскую вещь. Возвращаемое значение - это PID дочернего процесса, который только что появился.

Если это -1, произошла ошибка (очень странный случай), и если это 0, это означает, что вы сейчас выполняете в дочернем процессе, и вы должны сделать что-то еще - то, что ожидается от дочернего процесса делаем.

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

...