Multi Forks контролируется главной родительской трубой - PullRequest
0 голосов
/ 26 апреля 2010

У меня есть этот код, он работает плавно, но если я изменю NUM_CHILDREN = 2 или любое другое число «не равно 1», это плохой дескриптор файла. почему это?

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

enum {
    NUM_CHILDREN = 1
};

static int pipes[NUM_CHILDREN][2];

void start_encoding(void) {
    pid_t d, h;

    int pipe_master[2];
    pipe(pipe_master);
    if (d = fork()) {
        int j;
        for (j = 0; j < NUM_CHILDREN; j++) {
            int pipe_sub[2];
            pipe(pipe_sub);
            pipes[j][0] = pipe_sub[0];
            pipes[j][1] = pipe_sub[1];
            if (h = fork()) {
                dup2(pipes[j][0], 0);
                close(pipe_master[0]);
                close(pipe_master[1]);
                for (j = 0; j < NUM_CHILDREN; j++) {
                    close(pipes[j][0]);
                    close(pipes[j][1]);
                }
                execl("/bin/sort", "sort", NULL);
            } else {
                close(STDIN_FILENO);
                dup2(pipe_master[0], STDIN_FILENO);
                close(STDOUT_FILENO);
                dup2(pipes[j][1], STDOUT_FILENO);
                close(pipe_master[0]);
                close(pipe_master[1]);
                for (j = 0; j < NUM_CHILDREN; j++) {
                    close(pipes[j][0]);
                    close(pipes[j][1]);
                }
                execl("/bin/sed", "sed", "s/tty/TTY/g", NULL);
            }
        }
    } else {
        close(STDOUT_FILENO);
        dup2(pipe_master[1], STDOUT_FILENO);
        close(pipe_master[0]);
        close(pipe_master[1]);
        execl("/usr/bin/who", "who", NULL);
    }
} 

На самом деле я хочу смоделировать:

             -- sed
        |---|
        |    -- sort
  who --|
        |    -- sed
        |---|
        |    -- sort
        |
         --- ...

что мне использовать?

Ответы [ 2 ]

1 голос
/ 26 апреля 2010

Потому что в этих вложенных циклах:

for (j = 0; j < NUM_CHILDREN; j++) {
    close(pipes[j][0]);
    close(pipes[j][1]);
}

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

0 голосов
/ 26 апреля 2010

Этот код:

    for (j = 0; j < NUM_CHILDREN; j++) {
...
      if (h = fork()) {
...
            for (j = 0; j < NUM_CHILDREN; j++) {
                close(pipes[j][0]);
                close(pipes[j][1]);
            }
            execl("/bin/sort", "sort", NULL);

Будет пытаться закрыть каналы, которые еще не были открыты (если NUM_CHILDREN> 1)

Использование одной и той же переменной цикла (j) для внутреннего и внешнего циклов также является проблемой.

Другая проблема заключается в том, что вы делаете execl("/bin/sort") из родителя , поэтому внешний цикл никогда не сможет пройти первую итерацию.

...