简体   繁体   English

STDIN、STDOUT 重定向与 printf scanf 挂起

[英]STDIN, STDOUT redirection with printf scanf hangs

Can anyone find out why this code hang at fgets() for parent and scanf() for child?谁能找出为什么这段代码挂在父级的 fgets() 和子级的 scanf() 上?
If I turn child process's printf/scanf into write/read it doesn't hang.如果我将子进程的 printf/scanf 转换为写入/读取,它不会挂起。
Can any one give a reason to this problem?任何人都可以给出这个问题的原因吗?

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;
}

Output to stdout is by default line-buffered, meaning the stdout internal buffer is flushed when you print a newline ( '\\n' ).默认情况下,输出到stdout是行缓冲的,这意味着在打印换行符 ( '\\n' ) 时会刷新stdout内部缓冲区。 But that is only the default, when stdout is connected to a terminal or console.但这只是默认设置,当stdout连接到终端或控制台时。

Since you make stdout write to a pipe, it's no longer line-buffered, but fully buffered.由于您将stdout写入管道,因此它不再是行缓冲的,而是完全缓冲的。 That means the output will only be flushed when you fill up the internal buffer, or when explicitly doing by calling fflush(stdout) .这意味着只有在填满内部缓冲区或通过调用fflush(stdout)显式执行时才会刷新fflush(stdout)

Since your code as shown in the question doesn't flush the buffers, nothing will ever be written, which means the parent process will wait forever on input from fp_r which never comes.由于问题中显示的代码不会刷新缓冲区,因此永远不会写入任何内容,这意味着父进程将永远等待来自fp_r输入, fp_r该输入永远不会到来。 Since the parent process is locked, it will in turn not write to fp_w and the reading in the child-process will then also be blocked.由于父进程被锁定,因此它不会写入fp_w并且子进程中的读取也将被阻止。

The solution, as you have discovered, is to explicitly flush stdout after writing to it in the child-process.正如您所发现的,解决方案是在子进程中写入后显式刷新stdout

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM