Linux shell模拟:卡在多个管道上

时间:2012-09-07 23:00:02

标签: c++ linux fork pipe

我知道已经提出了类似的问题,但没有一个回复对我有帮助。我正在尝试实现一个微型Linux外壳并且卡在多个管道上。具有单个管道(例如ls | wc)的命令可以工作,但如果我添加第二个管道,则控制台上不会显示任何内容。这是我的代码。

void ExecuteCommand(NODE *cHead,NODE *oHead)
{
    int fd[10][2];  // file descriptors' array
    int nfdCnt = 0 ;    // file descriptors counter
    string strCmd;      // command
    string strOp = "";  // operator
    int nOpCnt = 0 ;    // operator count

    while(1)
    {
        if (cHead != NULL)  // cHead is head pointer to the linked list of commands.
        {
            strCmd =  GetCmdOROperator(&cHead); // get command
        }
        if (oHead == NULL)  // oHead is head pointer to the linked list of operators.
        {
            strOp = "";
        }
        else
        {
            strOp = GetCmdOROperator(&oHead);   // get operator
        }

        if (strOp.empty())  // no operator exists. single or last command in the chain.
        {
            // Fork the child process
            pid_t child_id = fork();

            if(child_id == 0)
            {
                // Execute the command

                if (nOpCnt) // if we previously encountered any operator
                {
                    close(fd[nfdCnt-1][FD_WRITE]);
                    dup2(fd[nfdCnt-1][FD_READ], FD_READ);   // read from pipe updated by previous command
                }

                // call execvp()

                exit(-1);
            }
            else
            {
                for (int i = 0 ; i < nfdCnt; i++)
                {
                    close(fd[nfdCnt][0]);
                    close(fd[nfdCnt][1]);
                }
                wait(NULL);
                break;
            }
        }

        if (strOp == "|")
        {
            nOpCnt++ ;

            if (pipe (fd[nfdCnt]) < 0)
            {
                printf("\npipe error");
                return ;
            }

            pid_t child_id = fork();
            if (child_id == 0)
            {
                close(fd[nfdCnt][FD_READ]); // we dont need this
                dup2(fd[nfdCnt][FD_WRITE], FD_WRITE);

                if(nOpCnt > 1) // if we have already encountered a pipe before
                {
                    dup2(fd[nfdCnt-1][FD_READ],FD_READ);
                    close(fd[nfdCnt-1][FD_WRITE]);
                }

                // call execvp()
                exit (-1);
            }
            else
            {
                nfdCnt++;
            }

        }

    }
}

2 个答案:

答案 0 :(得分:2)

我没有仔细查看你的代码,但看起来你正在打开文件描述符,在这种情况下,进程将阻止读取,因为即使你认为已经关闭它,有人也会打开写入方面。尝试在每个dup2之后添加一个关闭:

 dup2( fd[ nfdCnt - 1 ][ FD_READ ], FD_READ );
 close( fd[ nfdCnt - 1 ][ FD_READ ])

(另外,添加一些错误检查。dup2forkclose等等都可能失败。在向论坛发帖时跳过错误检查有时会很方便,但请确保在实际代码中不要省略它。)

答案 1 :(得分:1)

 if (strOp == "|")

在C中不起作用;使用strcmp来比较字符串。或许你误解了你的问题C而不是C ++?你使用什么语言编译器?