【问题标题】:piping stdin/out through multiple forks通过多个分叉管道标准输入/输出
【发布时间】:2014-01-24 07:10:19
【问题描述】:

我不知道为什么我可以通过一个 fork 成功管道,但不能通过 2。第一个示例给出的预期输出等同于“ps -A | grep bash”,第二个示例应该给出“ps -A | grep bash | wc -l" 这只是第一个输出产生的行数。相反,它没有输出,只是挂起。

这行得通:

#include <iostream>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>     

using namespace std;

int main(int argc, char* argv[])
{
    int p1[2], p2[2];               
    pipe(p1); pipe(p2);             
    pid_t pID;

    pID = fork();

    if (pID == 0)       
    {
        close(p2[0]);                               
        dup2(p2[1], 1);                     
        close(p2[1]);                       
        execlp("ps", "ps", "-A", 0);        // print all processes  
    }   
    else
    {   
        wait(pID);                          
        close(p2[1]);                       
        dup2(p2[0],0);                      
        close(p2[0]);                       
        execlp("grep", "grep", "bash", NULL);   // search for bash (in process list)
    }
}

但这不是:

#include <iostream>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>     

using namespace std;

int main(int argc, char* argv[])
{
    int p1[2], p2[2];               
    pipe(p1); pipe(p2);             
    pid_t pID;

    pID = fork();

    if (pID == 0)       
    {
        pID = fork();

        if (pID == 0)
        {   
            close(p2[0]);                               
            dup2(p2[1], 1);                     
            execlp("ps", "ps", "-A", 0);        // print all processes  
        }   
        else
        {   
            wait(pID);                          
            close(p2[1]);                       
            dup2(p2[0],0);                      
            close(p1[0]);                               
            dup2(p1[1], 1);                     
            execlp("grep", "grep", "bash", 0);  // search for bash (in process list)
        }
    }
    else
    {   
        wait(pID);
        close(p1[1]);                       
        dup2(p1[0],0);                      
        execlp("wc", "wc", "-l", 0);            // count lines
    }
}

【问题讨论】:

  • 有很多相关的问题。简短的回答是您没有关闭足够多的文件描述符。在对dup2() 进行适当调用后,三个进程中的每一个都应关闭 4 个管道描述符。如果你不这样做,那么grep 的标准输入有两个进程仍然可以写入它(grepwc),所以grep 永远不会得到 EOF,所以wc 永远不会得到 EOF ,所以一切都卡住了。
  • 不要在level0启动所有管道,在level1定义p1;和p2在level2,问题解决了。此外,不要混合 C 和 C++ 的东西......
  • @moeCake,谢谢,成功了。
  • Jonathan 的解决方案也有效。
  • 如果不是为了学习,可以使用popen()

标签: c++ c linux fork pipe


【解决方案1】:

正如 moeCoke 和 Leffeir 所说,如果您更改代码中的一行,它绝对可以正常工作。

#include <iostream>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>     

using namespace std;

int main(int argc, char* argv[])
{
    int p1[2], p2[2];               
    pipe(p1);            
    pid_t pID;

    pID = fork();

    if (pID == 0)       
    {
        pipe(p2);  // <-- call pipe for p2 here ---
        pID = fork();

        if (pID == 0)
        {   
            close(p2[0]);                               
            dup2(p2[1], 1);                     
            execlp("ps", "ps", "-A", 0);        // print all processes  
        }   
        else
        {   
            wait(pID);                          
            close(p2[1]);                       
            dup2(p2[0],0);                      
            close(p1[0]);                               
            dup2(p1[1], 1);                     
            execlp("grep", "grep", "p", 0);  // search for bash (in process list)
        }
    }
    else
    {   
        wait(pID);
        close(p1[1]);                       
        dup2(p1[0],0);                      
        execlp("wc", "wc", "-l", 0);            // count lines
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-28
    • 2017-05-11
    • 1970-01-01
    相关资源
    最近更新 更多