新终端提示后连接到 stdio 打印输出的管道

Pipes connected to stdio print output after new terminal prompt

我无法理解如何在 C 中进行基本的管道传输。我查看了关于这个主题的其他几个问题,它们要么是针对细微不同的问题,要么我在这方面离题太远了我不明白为什么答案对我的问题有好处。

下面的这个程序只是我做的一个简单测试,我试图让行为等同于在我的 shell 中键入 "ls | grep a"。 (我有一个家庭作业,我必须构建一个可以处理管道的 shell,但这是我理解管道甚至尝试家庭作业的第一步)。我得到了正确的输出,但终端提示最终出现在输出之前,看起来它没有正确终止。由于这与 shell 家庭作业有关,我担心这会影响成绩(无论如何让它看起来像这样感觉不对)。有什么建议吗?

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

int main()
{
    int fdpipe[2];


    pipe(fdpipe);
    int f1 = fork();
    if(f1 == 0)
    {
        close(fdpipe[1]);
        dup2(fdpipe[0],0);
        close(fdpipe[0]);
        execlp("/bin/grep","grep","a",NULL);
    }
    else
    {
        close(fdpipe[0]);
        dup2(fdpipe[1],1);
        close(fdpipe[1]);
        execlp("/bin/ls","ls",NULL);
        wait(NULL);
    }
    return 0;
}

这是我的终端输出示例。

1067: ls
a.out  test.c  test.cc
NathanE: ~/Desktop/playground
1068: ./a.out 
NathanE: ~/Desktop/playground
1069: a.out
(The beginning of this line is where my cursor is)

我期待的是:

1067: ls
a.out  test.c  test.cc
NathanE: ~/Desktop/playground
1068: ./a.out 
a.out
NathanE: ~/Desktop/playground
1069: (my cursor would go here)

子进程运行 grep,而父进程用 ls 替换自身。 wait(NULL) 什么都不做,因为成功 exec*() 永远不会 return.

因为return在ls完成后立即控制shell,所以shell可以在grep完成之前显示下一个提示。

您可以使用两种方法来避免这种情况:

  1. fork() 两个子进程,wait() 为它们

  2. 用管道链中的最后一个进程替换进程本身

只有在管道链中的最后一个进程完成后,两者都将确保控制 returned 到 shell。