简体   繁体   English

Shell 管道 C++ 未结束命令

[英]Shell Pipeline C++ not ending command

I have a problem with Pipelines on a Shell that I want to create in C++. I'm trying to pipeline firstly between two commands and when I run the program, it pipelines as it should be, but it does not end my file or program to come back to the command line.我想在 C++ 中创建 Shell 上的管道时遇到问题。我首先尝试在两个命令之间进行管道传输,当我运行该程序时,它会按应有的方式进行管道传输,但不会结束我的文件或程序回到命令行。 It's an infinite loop of entering everything without showing an error.这是输入所有内容而不显示错误的无限循环。

The code for the pipeline is the following:管道的代码如下:

if(countpipes!=0)
{
    pid_t pid;
    int pipefd[2];
    pipe(pipefd);
    for(int j=0; j<commands.size(); j++)
    {   //cout<<endl<<"IT of "<<j<<" "<<commands[j]<<endl;
        vector<string> all_commands = split(commands[j]);
        vector<string> next_commands;
        if(j!=commands.size()-1)
        {   //cout<<"Piped once"<<endl;
            pipe(pipefd);
        }
        if(j+1<commands.size())
        {
            next_commands = split(commands[j+1]);
        }
        char* arguments[all_commands.size()+1];
        arguments[all_commands.size()] = NULL;
        for (int k = 0; k < all_commands.size(); k++)
        {
            arguments[k] = (char*)all_commands[k].c_str();
        }

        char* next_arguments[next_commands.size()+1];
        next_arguments[next_commands.size()] = NULL;
        for (int l = 0; l < next_commands.size(); l++)
        {
            next_arguments[l] = (char*)next_commands[l].c_str();
        }
        pid = fork();
        //cout<<"Child: "<<pid<<endl;
        if (pid < 0) {
            // Showing an error
            perror("fork");
            exit(1);
        }
        if (pid == 0) {
            // Child Process
            if(j==0)
            {
                close(pipefd[0]);
                dup2(pipefd[1], STDOUT_FILENO);
                close(pipefd[1]);
                int result2;
                result2 = execvp(arguments[0], arguments);
                if(result2 < 0)
                {
                    perror("execvp");
                    exit(1);
                }
            }
            else
            {
                close(pipefd[1]);
                dup2(pipefd[0], STDIN_FILENO);
                close(pipefd[0]);
                int result;
                result = execvp(arguments[0], arguments);
                if (result < 0) {
                    perror("execvp");
                    exit(1);
                }
            }
        }
        else {
            //cout<<"Wait pid"<<endl;
            wait(NULL);
            //cout<<"Wait after pid"<<endl;
        }
    }
}

I'm using a vector of strings that takes each of the commands.我正在使用接受每个命令的字符串向量。 The final output for the pipeline looks like this and lets me introduce any text I want forever: https://imgur.com/LBvQRjF管道的最终 output 看起来像这样,让我永远介绍我想要的任何文本: https://imgur.com/LBvQRjF

The way you have your fork/exec set up, each child will only be connected to one pipe -- the first child connected (stdout) to the write end of a pipe, and each subsequent child connected (stdin) to the read end of a pipe. This will not work for 3+ children in a pipeline, as the middle children need to be connected to two (different) pipes -- stdin to the read end of one pipe and stdout to the write end of another.您设置 fork/exec 的方式,每个孩子将只连接到一个 pipe——第一个孩子连接(stdout)到 pipe 的写入端,每个后续孩子连接(stdin)到 pipe 的读取端a pipe。这不适用于管道中的 3 个以上的孩子,因为中间的孩子需要连接到两个(不同的)管道——stdin 连接到一个 pipe 的读取端,stdout 连接到另一个的写入端。

You are not closing the pipe ends in the parent, so any child that is reading from a pipe will never see an EOF -- even when the previous child that is writing to the pipe exits, the parent will still have the write end open.您没有关闭父级中的 pipe 端,因此从 pipe 读取的任何子级都永远不会看到 EOF——即使写入 pipe 的前一个子级退出时,父级仍将打开写入端。

You also seem to be creating a next_agruments argv that you then never use, which is useless and probably indicates some confusion in your design.您似乎还在创建一个next_agruments argv,然后您永远不会使用它,这是无用的,可能表明您的设计有些混乱。

pseudo-code for what you want:你想要的伪代码:

int prev_out = -1, pipefds[2];
for (each command in the pipeline) {
    if (not last command)
        pipe(pipefds);
    if ((child[i++] = fork()) == 0) {
        // child
        if (prev_out >= 0)
            dup2(prev_out, 0);
        if (not last command) {
            dup2(pipefd[1], 1);
            close(pipefd[0]); }
        execvp(...
    } else {
        // parent
        if (prev_out >= 0)
            close(prev_out);
        if (not last command) {
            close(pipefd[1]);
            prev_out = pipe_fd[0]; }
    }
}
// now wait for the children.

You need a pipe between each pair of children connecting them.你需要一个 pipe 在连接他们的每对孩子之间。 You need to close ALL the pipe fds in the parent after forking the children.分叉子项后,您需要关闭父项中的所有 pipe fds。 You don't want to wait for any of the children until you've created all of them.在创建所有子项之前,您不想等待任何子项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM