C ++ трубы между несколькими детьми - PullRequest
0 голосов
/ 02 ноября 2011

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

например, я беру аргументы командной строки, чтобы определить, сколько потомков будет создано. Первый дочерний элемент не имеет входных данных, но имеет выходные данные, а последний дочерний элемент выводит на выход STD Мне нужно передать значения в первого ребенка и каждого ребенка после этого по порядку. Вот что я получил:

#include <errno.h>
#include <cstdio>
#include <iostream>
#include <sys/wait.h>

using namespace std;

int main(int argc, char *argv[]) {
    pid_t childpid;
    int x2ypipe[2];
    pipe(x2ypipe);
    if(x2ypipe==0) {
        cout<<"ERROR:"<<errno<<endl;
    }
    int y2zpipe[2];
    pipe(y2zpipe);
    if(y2zpipe==0) {
        cout<<"ERROR:"<<errno<<endl;
    }
    pid_t xchild =fork();
    if(xchild==0) {
        dup2(x2ypipe[1],STDOUT_FILENO);
        close(x2ypipe[0]);
        close(x2ypipe[1]);
        int a=execl(argv[1],argv[1], (char*)NULL);
        if(a==-1) {
            perror("The following error occurred at A");
        }
    }
    for(int i=2; i<(argc-1); i++) {
        childpid =fork();
        if(childpid==0) {
            dup2(x2ypipe[0],STDIN_FILENO);
            close(x2ypipe[0]);
            close(x2ypipe[1]);
            //direct y2z pipe to standard output and replace the child with the program part2
            dup2(x2ypipe[1],y2zpipe[1]);
            dup2(y2zpipe[1],STDOUT_FILENO);
            close(y2zpipe[0]);
            close(y2zpipe[1]);
            int b=execl(argv[i],argv[i],(char *)NULL);
            if(b==-1) {
                perror("The following error occurred at B");
            }
        }
    }
    pid_t zchild =fork();
    if(zchild==0) {
        dup2(y2zpipe[0],STDIN_FILENO);
        close(y2zpipe[0]);
        close(y2zpipe[1]);
        int c=execl(argv[argc-1],argv[argc-1],(char *)NULL);
        if(c==-1) {
            perror("The following error occurred at C");
        }
    }
    close(x2ypipe[0]);
    close(x2ypipe[1]);
    wait(NULL);
    wait(NULL);
    wait(NULL);
}

сейчас я передаю только три программы в argv [], и все работает нормально. Мне придется добавить оператор if в цикл for, чтобы проверить последнее / максимально возможное значение i для соединения канала y2z с zchild. Что я испытываю затруднения, делая это, соединяя детей друг с другом в цикле for. Как мне создать новую трубу для каждого ребенка из последнего ребенка?

Ответы [ 2 ]

0 голосов
/ 02 ноября 2011

Может быть, это поможет.Обратите внимание, как я вызываю pipe() внутри моего цикла for, поэтому мне не нужно думать о новых именах "x2y", "y2z", "z2omega" и т. Д. И т. Д. Для пар каналов.

Такжеобратите внимание, как я использовал переменную prevfd извне цикла for для переноса дескриптора файла канала предыдущих итераций в следующую итерацию.И как он указывает на «/ dev / null» для начала.

Наконец, обратите внимание, как я называю wait() точно столько раз, сколько мне нужно, в цикле, а не записывая его 3 (или4 или 5 или ... 1397) раз.

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <cstdlib>
#include <cstdio>
#include <sys/wait.h>

int main(int argc, char *argv[]) {

  int prevfd;

  prevfd = open("/dev/null", O_RDONLY);

  if(prevfd < 0) {
    perror("/dev/null");
    exit(1);
  }

  for(int i = 1; i < argc; ++i) {
    int pipefd[2];
    int kid;

    if(i != argc-1 && pipe(pipefd)) {
      perror("pipe");
      break;
    }

    if(!fork()) {
      dup2(prevfd, 0);
      close(prevfd);
      if(i != argc-1) {
        dup2(pipefd[1], 1);
        close(pipefd[0]);
        close(pipefd[1]);
      }
      execl(argv[i], argv[i], (char*)0);
      perror(argv[i]);
      exit(1);
    }

    close(prevfd);
    prevfd = pipefd[0];
    close(pipefd[1]);
  }
  while(wait((int*)0) != -1)
    ;
  return 0;
}
0 голосов
/ 02 ноября 2011

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

...