Создание n детей, каждый со своей трубкой - PullRequest
2 голосов
/ 12 марта 2019

У меня проблемы с пониманием pipe и fork, по крайней мере, для практической реализации. Я хотел бы создать n детей, каждый со своей трубкой.

Я думал сделать что-то вроде:

int main(void) {
    int fd[2];
    for (int i = 0; i < n; i++) {
        pipe(fd);
        r = fork();

        if (r == 0) {
            // do child stuff
        } else if (r > 0) {
            // do parent stuff
        }
    }
}

Но это может привести к тому, что дети сами начнут делать процессы, а это не то, чего я хочу.

Более того, как бы вы сделали так, чтобы родитель и потомок работали одновременно, когда ребенок постоянно пишет в канал, а родитель, имеющий доступ к каналу для каждого ребенка, читает из него, что-то с ним делает, затем отбрасывает его, чтобы ребенок мог написать что-то новое в трубу?

1 Ответ

0 голосов
/ 12 марта 2019

Вам понадобится массив файловых дескрипторов, достаточно большой для одной пары файловых дескрипторов для каждого дочернего элемента.

Родительский код создаст каналы.Каждый дочерний процесс должен закрывать каналы любых процессов одного уровня.Точная механика этого зависит от того, как вы создаете трубы;Есть несколько возможных вариантов.

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

Родительский процесс просто продолжит создавать другие дочерние процессыпрежде чем идти в свой собственный цикл обработки.

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

В комментарии, который вы спрашиваете "... люди упомянули многопоточностьно возможно ли это с помощью pipe? », на что ответ« да, это возможно - хотя не ясно, является ли это необходимым или желательным ».

Возможно, у вас есть пример кодаделать то, что вы описали?

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

int main(void)
{
    enum { NUM_CHILDREN = 5 };
    int fd[NUM_CHILDREN][2];

    for (int i = 0; i < NUM_CHILDREN; i++)
    {
        pipe(fd[i]);
        int pid = fork();
        if (pid < 0)
           …error exit…
        if (pid == 0)
        {
            // Child
            // Close sibling pipes
            for (int j = 0; j < i; j++)
            {
                close(fd[j][0]);
                close(fd[j][1]);
            }
            close(fd[i][0]);   // Close read end of pipe
            be_childish(fd[i][1]);
            exit(EXIT_FAILURE);
        }
    }

    for (int i = 0; i < NUM_CHILDREN; i++)
        close(fd[i][1]);       // Close write end of every child's pipe

    // setup complete, unless you need to make the read end of the pipes non-blocking
    // do parental stuff, reading from the various child pipes

    for (int i = 0; i < NUM_CHILDREN; i++)
        close(fd[i][0]);       // Close read end of every child's pipe
    int corpse;
    int status;
    while ((corpse = wait(&status)) > 0)
        printf("Child %d exited with status 0x%.4X\n", corpse, status);

    return 0;
}

Осторожно: этот код не был рядом с компилятором, оченьменьше бегатьВ нем, вероятно, есть ошибки.

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