【问题标题】:C++ program to simulate ls|wc|wc using pipes does not display output after running successfully使用管道模拟ls|wc|wc的C++程序运行成功后不显示输出
【发布时间】:2017-04-15 14:30:35
【问题描述】:

程序执行,但未显示最终输出。我似乎弄乱了输出的管道。

删除了对 execlp()、pipe()、fork() 失败的检查,因为它们不会导致上述问题。

#include "iostream"
#include "stdlib.h"
#include "unistd.h"
#include "wait.h"
#include "stdio.h"
#include "fcntl.h"
using namespace std;
int main(int argc, char **argv)
{
    int fd[2],status,status2,fd1[2];
    pipe(fd);
    pipe(fd1);
    char buf[12];
    switch(fork())
    {
        case 0:
                close(fd[0]);
                dup2(fd[1],1);
                close(fd[1]);
                execlp("ls","ls",NULL);
                exit(0);
                break;
        default:
                waitpid(-1,&status,0);
                close(fd[1]);
                close(fd1[0]);
                dup2(fd1[1],1);
                close(fd1[1]);
                dup2(fd[0],0);
                close(fd[0]);
                execlp("wc","wc",NULL);
    }

    switch(fork())
    {
        case 0:
        close(fd1[1]);
        dup2(fd1[0],0);
        close(fd1[0]);
        execlp("wc","wc",NULL); //this is not being redirected to STDOUT
        exit(0);
        break;
     default:
      waitforpid(-1,&status2,0);
    }
    return 0;
}

【问题讨论】:

    标签: c++ linux bash pipe


    【解决方案1】:

    exec 系列函数不会产生单独的进程,而是替换当前进程。如the man page for execlp 中所述,execlp 仅在发生错误时才返回控制权。

    因此,如果所有forkexeclp 调用成功,您的程序将无法到达execlp 的第三次调用,因为第一个cases 中的一个始终会执行switch,并且其中一个它们取代了您的流程。

    同时,我建议您不要在实际问题中解析ls 输出,因为UNIX 中的文件名可能包含您可能无法解析的空白字符、换行符等,还有其他选项,例如@ 987654330@命令可以用'\0'分隔文件名。

    【讨论】:

    • 感谢您的全面回答
    【解决方案2】:

    似乎第二个 fork() 不会被执行,因为这两个进程将在 execlp 指令中变异为程序 'ls' 和 'wc' 的代码。 检查是否是这样,也许只需将第一个开关的默认设置中的 execlp 指令更改为第二个开关就足够了。

    【讨论】:

    • 在这种情况下它可以工作。你能解释一下“两个进程变异”是什么意思吗?
    • 基本上,exec 函数返回的唯一时间是出现错误。如果exec 成功,则调用它的进程将被调用中指定的程序替换(调用进程“变异”为指定的程序)。在您的第一个switch 中,在fork 调用exec 之后,子进程和父进程都不会在switch 语句之后运行您的程序。
    • 没错,当你调用 execlp 时,进程将执行的代码是在调用中指定的,而 execlp 指令下面的代码,正如他们所说,只有在出错的情况下才会执行。在这种情况下,第一个进程(命名为Parent)将执行fork,创建进程(命名为Child1),然后在te execlp中,Parent将开始执行'wc',child1开始执行'ls',所以Parent赢了'如果第一个 execlp 正确执行,则不执行第二个 fork()。
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    • 2017-07-26
    相关资源
    最近更新 更多