简体   繁体   English

为什么子进程在使用fork和pipe从父级的输出中输入stdin时正在等待?

[英]Why child process is waiting while using fork and pipes for stdin from parent's output?

I understood how fork and pipes work but i have a doubt regarding the flow of the child and parent process.Since we are using fork the order of execution of parent and child process is undefined but why child process is waiting for stdin from parent process.What happens if child process executes first? 我了解fork和pipe的工作原理,但是我对子进程和父进程的流程有疑问。由于我们使用fork,因此父子进程的执行顺序是不确定的,但是为什么子进程要等待父进程的stdin。如果子进程首先执行会怎样? it must print empty in console? 它必须在控制台中打印为空吗? but it is not happening can i know why? 但是这没有发生我能知道为什么吗?

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h>
int main () {
int fds[2]; pid_t pid;
/* File descriptors for the two ends of the pipe are placed in fds. */
pipe (fds);
/* Fork a child process. */ 
pid = fork ();
if (pid == (pid_t) 0) {
/* Child proces -. Close the write end of the file descriptor. */
close (fds[1]);
/* Connect the read end of the pipe to standard input. */
dup2 (fds[0], STDIN_FILENO);
/* Replace the child process with the “rev” program. */
execlp("rev", "rev", 0); }

else {
/* This is the parent process. */
    FILE* stream;
/* Close the read end of the file descriptor. */
    close (fds[0]);
/* Convert the write file descriptor to a FILE object */
    stream = fdopen (fds[1], "w");
    fprintf (stream, ",ereh ot ereht morF\n");
    fprintf (stream, ",ereht ot ereh dna\n");
    fprintf (stream, ".erehwyreve era sgniht ynnuf\n"); 
    fprintf (stream, "ssueS .rD - \n");
    fflush (stream);
    close (fds[1]);
/* Wait for the child process to finish. */
    waitpid (pid, NULL, 0);
}
    return 0; 
}

You aren't closing enough file descriptors in the child. 您没有在子级中关闭足够的文件描述符。

Rule of thumb : If you dup2() one end of a pipe to standard input or standard output, close both of the original file descriptors returned by pipe() as soon as possible. 经验法则 :如果将管道的一端dup2()为标准输入或标准输出,请尽快关闭pipe()返回的两个原始文件描述符。 In particular, you should close them before using any of the exec*() family of functions. 特别是,在使用任何exec*()系列函数之前,应关闭它们。

The rule also applies if you duplicate the descriptors with either dup() or fcntl() with F_DUPFD 如果您使用带有F_DUPFD dup()fcntl()复制描述符,则该规则也适用

In this case, the child needs to close fds[1] after duplicating it. 在这种情况下,孩子需要在复制后关闭fds[1] Because it is still open, rev will never receive EOF because there is a process (the rev child process) that could, in theory, write to the input. 由于它仍处于打开状态,因此rev将永远不会收到EOF,因为从理论上讲,有一个可以写入输入的进程( rev子进程)。

You should use fclose(stream) instead of close(fds[1]) because the output is buffered and fclose() knows to flush the buffers, but close() hasn't got a clue. 您应该使用fclose(stream)而不是close(fds[1])因为输出已缓冲,并且fclose()知道要刷新缓冲区,但是close()没有任何线索。 However, by using fflush(stream) before the misguided close() , you do avoid problems. 但是,通过在误导的close()之前使用fflush(stream) close() ,可以避免出现问题。

That leads to: 这导致:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void)
{
    int fds[2];
    pid_t pid;

    pipe(fds);

    pid = fork();
    if (pid == (pid_t)0)
    {
        close(fds[1]);
        dup2(fds[0], STDIN_FILENO);
        close(fds[1]);
        execlp("rev", "rev", 0);
    }
    else
    {
        FILE *stream;
        close(fds[0]);
        stream = fdopen(fds[1], "w");
        fprintf(stream, ",ereh ot ereht morF\n");
        fprintf(stream, ",ereht ot ereh dna\n");
        fprintf(stream, ".erehwyreve era sgniht ynnuf\n");
        fprintf(stream, "ssueS .rD - \n");
        fclose(stream);
        waitpid(pid, NULL, 0);
    }
    return 0;
}

which produces the output: 产生输出:

From there to here,
and here to there,
funny things are everywhere.
 - Dr. Seuss

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

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