【问题标题】:output not displaying after piping with fork and exec使用 fork 和 exec 管道后不显示输出
【发布时间】:2017-08-06 20:11:19
【问题描述】:

我正在尝试创建一个函数,该函数运行一个命令,然后将输出通过管道传输到第二个命令并运行它。我正在无限循环中运行该函数。问题是,该功能第一次工作,但之后没有显示任何内容。 例如,当我运行ls | wc -l 时,它第一次显示正确的结果,但之后运行时却没有输出。

这是我的函数(解析在另一个函数中处理):

void system_pipe(std::string command1, std::string command2)
{
    int status;
    int fd[2];
    int fd2[2];
    pipe(fd);

    int pid = fork();
    // Child process.
    if (pid == 0)
    {
        std::shared_ptr<char> temp = string_to_char(command1);
        char *name[] = {"/bin/bash", "-c", temp.get(), NULL};

        close(fd[0]);
        dup2(fd[1], 1);
        execvp(name[0], name);

        exit(EXIT_FAILURE);
    }
    // Parent process.
    else
    {
        std::shared_ptr<char> temp = string_to_char(command2);
        char *name[] = {"/bin/bash", "-c", temp.get(), NULL};   

        close(fd[1]);
        dup2(fd[0], 0);
        waitpid(pid, &status, 0);
        //my_system(command2);

        // Fork and exec a new process here.
        int pid2 = fork();
        if (pid2 == 0)
        {
            execvp(name[0], name);
            exit(EXIT_FAILURE);
        }
        else
        {
            waitpid(pid2, NULL, 0);
        }
    }

    if (status)
        std::cout << "Bad" << std::endl;
}

我这样调用函数:

while(true)
{
    string line;
    getline(cin, line);
    pair<string, string> commands = parse(line);
    system_pipe(commands.first, commands.second);
}

为什么该函数只在第一个循环中正常工作?之后有什么变化?

【问题讨论】:

    标签: c++11 pipe fork exec


    【解决方案1】:
    else
     { 
            std::shared_ptr<char> temp = string_to_char(command2);
            char *name[] = {"/bin/bash", "-c", temp.get(), NULL};   
    
            close(fd[1]);
            dup2(fd[0], 0);
            waitpid(pid, &status, 0);
            //my_system(command2);
    

    我相信这不是你的意图。 dup2 必须在 child 中调用。

    int pid2 = fork();
    if (pid2 == 0)
    {
        dup2(fd[0], 0); // here.
        execvp(name[0], name);
        exit(EXIT_FAILURE);
    }
    

    第二个问题是您让管道文件处于打开状态。 这不是一个好的编码示例,但它只是为了说明它应该如何工作。

    // ( g++ -std=c++11  )
    // type `ls | grep file.cxx`
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <array> 
    #include <memory>
    
    #include <sys/wait.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    void replace_with ( std::string command )
    {
        char exec_name [] = "bash" , arg [] = "-c" ;
        char * line [] = { exec_name , arg , &command[ 0 ] , nullptr } ;
        execvp( exec_name , line ) ;
    }
    
    void pipeline ( const std::string& command0 , const std::string& command1 )
    {
        std::array< int , 2 > pipe_fd ; enum { READ_END , WRITE_END } ; 
    
        if ( pipe( pipe_fd.data() ) ) throw std::runtime_error( "can't create a pipe" ) ;
    
        int id = fork() ;
        if ( id < 0 ) { for ( auto each : pipe_fd ) close( each ) ;
                        throw std::runtime_error( "can't create a child" ) ; }
    
        if ( ! id ) /* child */
        {
            close( pipe_fd[ READ_END ] ) ; 
            dup2( pipe_fd[ WRITE_END ] , STDOUT_FILENO ) ;
            close( pipe_fd[ WRITE_END ] ) ; //
    
            replace_with( command0 ) ;
        }
        else /* parent */
        {
            close( pipe_fd[ WRITE_END ] ) ;
            waitpid( id , nullptr , 0 ) ;
            int id_second = fork () ;
            if ( id_second > 0 ) waitpid( id_second , nullptr , 0 ) ;
            else if ( ! id_second ) /* child */ 
            {
                dup2( pipe_fd[ READ_END ] , STDIN_FILENO ) ;
                close( pipe_fd[ READ_END ] ) ; //
                replace_with( command1 ) ;
            }
    
            close( pipe_fd[ READ_END ] ) ;
        }
    }
    
    int main () try
    {
        while ( true )
        {
            std::string command0 , command1 ;
            getline( std::cin , command0 , '|' ) ;
            getline( std::cin , command1 ) ;
            pipeline( command0 , command1 ) ;
        }
    
    } catch ( const std::runtime_error& e ) 
      { std::cerr << e.what() ; return - 1 ; }
    

    【讨论】:

      猜你喜欢
      • 2012-10-25
      • 2013-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-23
      • 2018-05-15
      • 1970-01-01
      • 2014-05-31
      相关资源
      最近更新 更多