子进程在重定向的标准输出上打印,父进程从未收到

时间:2018-12-13 15:15:08

标签: c pipe fork

我是C语言的初学者,我正在编写此程序,该程序的开头有一个数组,并且必须分叉两次,以便有两个子进程。每个子进程都获取父级数组的一半,并基于该数组执行程序,从而使其递归。

当孩子得到一个仅包含一个元素的数组时,该元素将打印在stdout上,然后退出。

然后,每个父级读取其两个子级在stdout上发送的内容,并根据该值进行计算。计算的结果是一个数组,然后该数组也被打印在stdout上,用于父级的父级计算。

什么不起作用: 我要结束递归并在每个孩子中打印出1元素数组的值,但是父对象似乎无法读取它。 它永远不会进入使用fgets()的while循环。

这是父级中将数组分为两部分的部分。在这里,我还给出了值(不做任何其他事情),以防我得到带有一个值的数组:

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]);

这是计算的一部分,之后父级将打印出计算出的数组:

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 :(得分:0)

  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;
}