can';在子进程退出之前,是否不读取流?

can';在子进程退出之前,是否不读取流?,c,stream,pipe,fork,redirect,C,Stream,Pipe,Fork,Redirect,好的,我有一个程序,可以创建两个管道->分叉->子对象的stdin和stdout被重定向到每个管道的一端->父对象连接到管道的另一端,并尝试读取与子对象的输出相关联的流并将其打印到屏幕上(最终我还将使其写入子对象的输入) 问题是,当父级尝试fgets子级的输出流时,它只是暂停并等待,直到子级死为fgets,然后打印输出。如果孩子不退出,它将永远等待。发生了什么事?我认为fgets可能会一直阻塞直到流中有东西,但不会一直阻塞直到孩子放弃它的文件描述符 代码如下: #包括 #包括 #包括 #包括

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

问题是,当父级尝试fgets子级的输出流时,它只是暂停并等待,直到子级死为fgets,然后打印输出。如果孩子不退出,它将永远等待。发生了什么事?我认为fgets可能会一直阻塞直到流中有东西,但不会一直阻塞直到孩子放弃它的文件描述符

代码如下:

#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[]){
文件*fpin;
文件*fpout;
int输入_fd[2];
int输出_fd[2];
pid_t pid;
智力状态;
字符输入[100];
字符输出[100];
char*args[]={“/somepath/someprogram”,NULL};
fgets(input,100,stdin);//用户输入要执行的程序名
管道(输入_fd);
管道(输出_fd);
pid=fork();
如果(pid==0){
关闭(输入_fd[1]);
关闭(输出_fd[0]);
dup2(输入_fd[0],0);
dup2(输出_fd[1],1);
输入[strlen(输入)-1]='\0';
execvp(输入,args);
}
否则{
关闭(输入_fd[0]);
关闭(输出_fd[1]);
fpin=fdopen(输入_fd[1],“w”);
fpout=fdopen(输出[0],“r”);
而(!feof(fpout)){
fgets(输出,100,fpout);
printf(“输出:%s\n”,输出);
}
}
返回0;
}

子对象可能应该
其输出,和/或正确终止行。否则,I/O缓冲区可能会保留数据相当长的一段时间


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

Hmmm,你是对的。当我刷新输出时,它就工作了。问题是,我无法控制这个孩子。我只能用我的测试程序来控制它,因为我可以编辑源代码。。。我如何确保任何被执行的程序的输出都是刷新的或非缓冲的或其他的。。。arghhwait,这是测试子项的代码:printf(“输入:\n”);fflush(stdout);如果我取出/n或fflush,它会延迟。。我需要它在没有a/n和。。如果没有我,我可能不应该使用FGET。。。但不确定这是否能解决问题。问题完全在孩子方面。如果子进程正在使用行缓冲IO,并且写入时没有换行符或
fflush()
,则数据永远不会离开子进程-没有其他人可以做任何事情。@caf:但是子进程的文件描述符是由父进程创建的,因此可以在子进程获得控制权之前对其设置选项。
#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;
}