Дочерний процесс печатает на перенаправленном stdout, родитель никогда не получает - PullRequest
0 голосов
/ 13 декабря 2018

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

Когда дочерний элемент получает массив, содержащий только один элемент, этот элемент выводится на стандартный вывод, а затем завершается.

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

Что не работает: я заканчиваю рекурсию и распечатываю значение1-элементный массив в каждом дочернем элементе, но родитель не может его прочитать.Он никогда не входит в цикл while, где я использую fgets ().

Это часть в parent, где я делю массив на две части.Здесь я также выдаю значение (не делая ничего другого) на случай, если я получу массив с одним значением:

while( fgets(strBuffer, sizeof(strBuffer), stdin)!= NULL){

  if(counter % 2 == 0){

    if(evenCounter == evenMax){
      evenMax++;
      evenBuffer = (char**) realloc(evenBuffer, evenMax * 
      sizeof(char*));

   }if(evenBuffer == NULL){
     fprintf(stderr, "error reallocating evenBuffer\n");
     exit(1);
   }

    evenBuffer[evenCounter] = (char*) malloc(100*sizeof(char));
    strcpy(evenBuffer[evenCounter], strBuffer);
    evenCounter += 1;

  } else {

    if(oddCounter == oddMax){
      oddMax ++;
      oddBuffer = (char**) realloc(oddBuffer, oddMax * 
            sizeof(char*));
    }if(oddBuffer == NULL){
      fprintf(stderr, "error reallocating oddBuffer\n");
      exit(1);
    }

    oddBuffer[oddCounter] = (char*) malloc(100*sizeof(char));
    strcpy(oddBuffer[oddCounter], strBuffer);
    ddCounter += 1;
  }

  counter ++;

}

if(counter == 1){
  fprintf(stdout, "%s\n", evenBuffer[0]);
  //  fprintf(stderr, "LAAAAST %s\n", evenBuffer[0]);
  fflush(stdout);
  exit(0);
}


if(oddCounter != evenCounter){
  fprintf(stderr, "evenCounter size:%d, oddCounter:%d\n", 
  evenCounter, oddCounter);
  exit(EXIT_FAILURE);
}

Вот часть кода, где создаются дочерние элементы, а каналы создаются и перенаправляются.

  int k1pipe_from[2];
  int k1pipe_to[2];
  pipe(k1pipe_from);
  pipe(k1pipe_to);

  int k2pipe_from[2];
  int k2pipe_to[2];
  pipe(k2pipe_from);
  pipe(k2pipe_to);

  pid_t pid = fork();
  pid_t pid2;

 switch(pid){
  case -1:
    fprintf(stderr, "Cannot fork!\n");
    exit(EXIT_FAILURE);
  case 0://child 1
    fprintf(stderr, "Child 1 created, pid: %d\n", getpid());

    close(k2pipe_from[1]);
    close(k2pipe_to[0]);

    close(k1pipe_from[1]);
    close(k1pipe_to[0]);

    dup2(k1pipe_from[0], STDIN_FILENO);
    close(k1pipe_from[0]);
    dup2(k1pipe_to[1], STDOUT_FILENO);
    close(k1pipe_to[1]);

    fflush(stdout);
    execl("forkFFT", "forkFFT", NULL);
    break;
 default:
   close(k1pipe_to[1]);
   close(k1pipe_from[0]);
   fflush(stdout);
}

pid2 = fork();
switch(pid2){
  case -1:
   fprintf(stderr, "Cannot fork!\n");
   exit(EXIT_FAILURE);
  case 0://child 2
   close(k1pipe_from[1]);
   close(k1pipe_to[0]);
   close(k2pipe_from[1]);
   close(k2pipe_to[0]);

   dup2(k2pipe_from[0], STDIN_FILENO);
   close(k2pipe_from[0]);
   dup2(k2pipe_to[1], STDOUT_FILENO);
   close(k2pipe_to[1]);
   fflush(stdout);

   execl("forkFFT", "forkFFT", NULL);
   break;
  default:
   close(k2pipe_to[1]);
   close(k2pipe_from[0]);
}

Вот часть, где я читаю, что один из дочерних процессов записал на своем перенаправленном stdout.

FILE* k1File = fdopen(k1pipe_to[0], "r+");
char r1Buffer[1000];
evenResCounter = 0;
char* pend1;

while(fgets(r1Buffer, strlen(r1Buffer), k1File) != NULL){
  double real = (double) strtof(r1Buffer, &pend1);
  double img = 0.00;
  if(pend1 != NULL){
    img = (double) strtof(pend1, NULL);
  }

  evenRes[evenResCounter] = real + img * I;

  evenResCounter ++;

}

close(k1pipe_to[0]);

Вот часть с вычислением, после которойparent распечатывает вычисленный массив:

double pi = 3.141592654;
int total_elem = evenResCounter + oddResCounter;
double complex transArray[total_elem];
int k = 0;
int half = total_elem/2;

while(k <= half){
  transArray[k] = evenRes[k] + (cos(-2*pi/total_elem*k) + I * sin(-2*pi/total_elem*k)) * oddRes[k];
  transArray[k + half] = evenRes[k] - (cos(-2*pi/total_elem*k) + I * sin(-2*pi/total_elem*k)) * oddRes[k];
  k++;
}

int final_counter = 0;
while(final_counter != total_elem){
  fprintf(stdout, "%f %f*i\n", creal(transArray[final_counter]), cimag(transArray[final_counter]));
}

Буду очень признателен за любую помощь.

1 Ответ

0 голосов
/ 14 декабря 2018
  1. Вы должны получить pipe для дочернего сообщения, отправляемого родителю
  2. В дочернем, перенаправить stdout в pipe, рекурсивные или просто выходные данные
  3. В родительском,перенаправить stdin в pipe, получить данные, если в main process, позвонить calculation(), в противном случае просто позвонить output_data()

Следующий код просто получить сумму всех данных, выможет изменить его в calculation():

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

int sum = 0;

void output_data(int data) {
  printf("%d\n", data);
}

void calculation(int data) {
  sum += data;
}

void child(int* array, int left, int right, bool in_main_process) {
  if (left == right)
    exit(0);
  if (left + 1 == right) {
    in_main_process ? calculation(array[left]) : output_data(array[left]);
    exit(0);
  }

  int mid = (left + right) / 2;

  int pipe_fd_1[2];
  pipe(pipe_fd_1);

  if (fork() == 0) { // child 1
    close(pipe_fd_1[0]);
    dup2(pipe_fd_1[1], STDOUT_FILENO);
    close(pipe_fd_1[1]);
    child(array, left, mid, false);
    exit(1);
  }

  int pipe_fd_2[2];
  pipe(pipe_fd_2);
  if (fork() == 0) { // child 2
    close(pipe_fd_2[0]);
    dup2(pipe_fd_2[1], STDOUT_FILENO);
    close(pipe_fd_2[1]);
    child(array, mid, right, false);
    exit(1);
  }

  close(pipe_fd_1[1]);
  dup2(pipe_fd_1[0], STDIN_FILENO);
  close(pipe_fd_1[0]);

  int data;
  while (scanf("%d", &data) == 1)
    in_main_process ? calculation(data) : output_data(data);

  close(pipe_fd_2[1]);
  dup2(pipe_fd_2[0], STDIN_FILENO);
  close(pipe_fd_2[0]);

  while (scanf("%d", &data) == 1)
    in_main_process ? calculation(data) : output_data(data);
}

int main() {
  int array[6] = {1, 2, 3, 4, 5, 6};

  int left  = 0;
  int right = sizeof(array) / sizeof(array[0]);
  child(array, left, right, true);
  printf("%d\n", sum);

  return 0;
}
...