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

Bob*_*rbo 5 c redirect fork pipe stream

好的我有一个程序可以创建两个管道 - >分叉 - >孩子的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;
}
Run Code Online (Sandbox Code Playgroud)

unw*_*ind 5

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

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