直到孩子退出才能从溪流中读取?

时间:2010-04-26 11:22:12

标签: c stream pipe fork redirect

好的我有一个创建两个管道的程序 - >叉子 - >将孩子的stdin和stdout重定向到每个管道的一端 - >父连接到管道的另一端,并尝试读取与子输出相关联的流并将其打印到屏幕上(我也将最终写入子输入)。

问题是,当父级尝试fgets子级的输出流时,它只会停止并等待直到子级死于fgets然后打印输出。如果孩子没有退出,它就会永远等待。到底是怎么回事?我想也许fgets会阻塞,直到SOMETHING在流中,但是在孩子放弃文件描述符之前不会一直阻塞。

这是代码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
 FILE* fpin;
 FILE* fpout;
 int input_fd[2];
 int output_fd[2];
 pid_t pid;
 int status;
 char input[100];
 char output[100];
 char *args[] = {"/somepath/someprogram", NULL};
 fgets(input, 100, stdin); // the user inputs the program name to exec

 pipe(input_fd);
 pipe(output_fd);
 pid = fork();

 if (pid == 0) {
  close(input_fd[1]);
  close(output_fd[0]);
  dup2(input_fd[0], 0);
  dup2(output_fd[1], 1);
  input[strlen(input)-1] = '\0';
  execvp(input, args);
 }
 else {
  close(input_fd[0]);
  close(output_fd[1]);
  fpin = fdopen(input_fd[1], "w");
  fpout = fdopen(output_fd[0], "r");
  while(!feof(fpout)) {
   fgets(output, 100, fpout);
   printf("output: %s\n", output);
  }
 }

 return 0;
}

#include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <unistd.h> int main(int argc, char *argv[]) { FILE* fpin; FILE* fpout; int input_fd[2]; int output_fd[2]; pid_t pid; int status; char input[100]; char output[100]; char *args[] = {"/somepath/someprogram", NULL}; fgets(input, 100, stdin); // the user inputs the program name to exec pipe(input_fd); pipe(output_fd); pid = fork(); if (pid == 0) { close(input_fd[1]); close(output_fd[0]); dup2(input_fd[0], 0); dup2(output_fd[1], 1); input[strlen(input)-1] = '\0'; execvp(input, args); } else { close(input_fd[0]); close(output_fd[1]); fpin = fdopen(input_fd[1], "w"); fpout = fdopen(output_fd[0], "r"); while(!feof(fpout)) { fgets(output, 100, fpout); printf("output: %s\n", output); } } return 0; }

1 个答案:

答案 0 :(得分:5)

孩子应该fflush()输出,和/或正确终止线路。否则,I / O缓冲可能会持续很长一段时间。

您可以尝试在切换控件之前在子项的输出文件描述符上设置O_NONBLOCK标志(使用fcntl()),但这需要您相应地更改父代码。正如评论中指出的那样,如果孩子使用基于FILE的I / O,这将无法帮助您克服在C标准库级别完成的缓冲。