【问题标题】:Execute a console program, write to standard input and read result with pipe [closed]执行控制台程序,写入标准输入并使用管道读取结果[关闭]
【发布时间】:2014-12-28 09:46:49
【问题描述】:

我需要执行我的控制台程序,将一些值写入标准输入并使用管道读取结果。我试图实现它。此代码完美运行。但我认为还有其他更简单的方法来实现它。你有什么想法吗?

pid_t pid = fork();
std::string output_data;
if(pid < 0)
{
    printf("Error\n");
}
else if(!pid)
{
    FILE* process = popen(program.c_str(), "r");
    char temp_data[128];
    if(process)
    {
        while(fgets(temp_data, sizeof(temp_data), process))
        {
            output_data.append(temp_data);
        }
    }
    pclose(process);
    exit(1);
}
else
{
    FILE* process = popen(program.c_str(), "w");
    std::string output_data;
    char temp_data[128];
    if(process)
    {
        fwrite("5", 1, sizeof(int), process);
    }
    pclose(process);
}

【问题讨论】:

    标签: c++ linux gcc pipe


    【解决方案1】:

    看起来您的代码将运行 4 个进程:一个进程分叉成 2 个,然后每个进程都使用 popen() 分叉。 popen() 不仅会创建一个管道,还会创建一个通过该管道连接的子进程,因此调用 popen() 的 2 个进程中的每一个都会创建一个子进程。

    你应该决定如何去做:要么让 popen() 完成所有工作,但不要使用 fork(),或者让 pipe() 自己创建管道并使用 fork() - 这就是我的代码下面是。

    还有一个很大的区别:popen() 不仅会 fork,还会在子进程中执行另一个程序。我的示例保留在同一个可执行文件中。如果你想在子进程中执行另一个程序,那么 popen() 会很有用,但是你不应该使用 fork()。

    int fsd[2]; // write to fds[1], read from fds[0]
    pipe(fds);  // creates the pipe with read+write file descriptors in fds
    id_t pid = fork();
    std::string output_data;
    if(pid < 0)
    {
        printf("Error\n");
    }
    else if(!pid)
    {
        close(fds[1]); // else we'll never detect end of input
        FILE* process = fdopen(fds[0], "r");
        char temp_data[128];
        if(process)
        {
            while(fgets(temp_data, sizeof(temp_data), process))
            {
                output_data.append(temp_data);
            }
        }
        pclose(process);
        exit(1);
    }
    else
    {
        close(fds[0]); // just to clean up
        FILE* process = fdopen(fds[1], "w");
        std::string output_data;
        char temp_data[128];
        if(process)
        {
            fprintf(process, "5\n"); // your fwrite("5",...) worked by luck only
        }
        pclose(process);
    }
    

    最后,如果您希望您的进程启动另一个可执行文件,写入该可执行文件然后从中读取,您需要这样做:

    创建 2 个管道,一个用于从父级写入子级,一个用于从子级向父级回写,然后做一些魔术重新分配文件描述符:

    int p2c[2]; pipe(p2c); // parent to child
    int c2p[2]; pipe(c2p); // child to parent
    if(fork()) { // parent -  I ignore error checks here
        close(p2c[0]); // the child reads from that
        close(c2p[1]); // the child writes to that
        FILE * f_w = fdopen(p2c[1],"w");
        ... write some data to the child using f_w ...
        fclose(f_w);
        FILE * f_r = fdopen(c2p[0],"r");
        ... read some data from the child using f_r ...
        fclose(f_r);
        wait(0); // just to avoid a zombie
    } else { // in the child, change stdin and stdout
        close(p2c[1]); close(0); dup(p2c[0]); close(p2c[0]);
        close(c2p[0]); close(1); dup(c2p[1]); close(c2p[1]);
        ... now use execv or something similar to run the other executable
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-26
      • 1970-01-01
      • 2013-09-27
      • 1970-01-01
      • 1970-01-01
      • 2013-11-04
      • 2012-03-13
      • 2012-10-31
      相关资源
      最近更新 更多