C语言 STDIN,带有 printf scanf 挂起的 STDOUT 重定向



谁能找出为什么这段代码挂在 fgets(( 的 parent 和 scanf(( 的子级
如果我将子进程的 printf/scanf 转换为写入/读取,它不会挂起。
任何人都可以给出这个问题的理由吗?

int main(){
int pfd1[2], pfd2[2];
pipe(pfd1); pipe(pfd2);
if (fork() == 0){
dup2(pfd1[1], STDOUT_FILENO);
dup2(pfd2[0], STDIN_FILENO);
close(pfd1[0]); close(pfd1[1]);
close(pfd2[1]); close(pfd2[0]);
char buf[] = "Hello worldn";
int n;
printf("%s", buf);
fflush(stdin);
scanf("%d", &n);
fprintf(stderr, "get n = %dn", n);
}    
else {
char buf[128];
FILE *fp_w = fdopen(pfd2[1], "w");
FILE *fp_r = fdopen(pfd1[0], "r");
fgets(buf, 128, fp_r);
printf("%s", buf);
fprintf(fp_w, "%dn", 10);
}
return 0;
}

> 输出到stdout默认是行缓冲的,这意味着当您打印换行符 ('n'( 时,stdout内部缓冲区将被刷新。这只是默认设置,当stdout连接到终端或控制台时。

由于stdout写入管道,因此它不再是行缓冲的,而是完全缓冲的。这意味着只有在填满内部缓冲区或通过调用fflush(stdout)显式执行时,才会刷新输出。

由于问题中显示的代码不会刷新缓冲区,因此不会写入任何内容,这意味着父进程将永远等待来自永远不会出现的fp_r输入。由于父进程被锁定,它反过来不会写入fp_w子进程中的读取也会被阻止。

正如您所发现的,解决方案是在子进程中写入stdout后显式刷新。

最新更新