任何人都可以找出为什么此代码卡在父级的 fgets() 和子级的 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 world\n";
int n;
printf("%s", buf);
fflush(stdin);
scanf("%d", &n);
fprintf(stderr, "get n = %d\n", 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, "%d\n", 10);
}
return 0;
}
最佳答案
默认情况下,stdout
的输出是行缓冲的,这意味着当您打印换行符时,stdout
内部缓冲区将被刷新('\n'
)。 但是这只是当stdout
连接到终端或控制台时的默认设置。
由于您将stdout
写入管道,它不再是行缓冲的,而是完全缓冲的。这意味着只有当您填满内部缓冲区时,或者通过调用 fflush(stdout) 显式执行操作时,输出才会被刷新。
由于问题中所示的代码不会刷新缓冲区,因此不会写入任何内容,这意味着父进程将永远等待来自 fp_r
的输入,而该输入永远不会到来。由于父进程被锁定,因此它不会写入 fp_w
并且子进程中的读取也将被阻止。
正如您所发现的,解决方案是在子进程中写入后显式刷新 stdout
。
关于c - 使用 printf scanf 进行 STDIN、STDOUT 重定向挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59016862/