C语言中的管道命令问题

时间:2009-11-07 22:48:01

标签: c unix pipe piping

我正在尝试在C中为Unix创建一个简单的shell。我已经能够完成所有命令和执行的解析,但是我遇到了管道问题。我认为问题是我没有连接到正确的管道输入第二个命令。

例如,如果我输入“ls | wc”,它将在“wc”命令后暂停,我认为这是因为它等待输入。我认为问题是当我使用dup2(读取[i],0),而不是挂钩到正确的管道时。

我知道这是一个广泛的问题,但如果有任何指示我可以得到,我会很感激。这是创建新进程并尝试管道它们的代码。

    int fileds[2];
    int reading[num_cmds];
    int writing[num_cmds];

    int p;
    for(p=0; p < num_cmds; p++)
    {
        reading[p] = -1;
        writing[p] = -1;
    }

    int j;
    for(j=0; j < num_cmds-1; j++)    //Create pipes for commands
    {
        int fileds[2];
        pipe(fileds);
        reading[j+1] = fileds[0];
        writing[j] = fileds[1];
    }

    int i = 0;
    for(i = 0; i < num_cmds;i++)
    {           
        cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg); //Get command and args

        pid_t childpid;
        int status;
        childpid=fork();

        if (childpid >= 0) 
        {
            if (childpid == 0) 
            {               
                if(writing[i] != -1)
                {
                    dup2(writing[i],1);
                    close(writing[i]);
                }

                if(reading[i] != -1)
                {
                    dup2(reading[i],0);
                    close(reading[i]);
                }

                int h;
                for(h = 0; h < num_cmds; h++)
                {
                    close(writing[h]);
                    close(reading[h]);
                }

                if(execvp(cmd_args[0],cmd_args) == -1) 
                {
                    perror("Problem with command");
                    exit(0);
                }
            }
            else 
            {
                wait(&status);
                int m;
                for(m = 0; m < num_cmds; m++)
                {
                    if( writing[m] != -1) close(writing[m]);
                    if( reading[m] != -1) close(reading[m]);
                }
            }
        }
        else 
        {
             perror("fork"); 
             continue;
        }


        input_file[0] = 0;
        output_file[0] = 0;
        run_bg = 0;
    }

}



更新:感谢理查德,我能够弄明白。它是以错误的顺序关闭文件描述符而根本不关闭一些文件描述符的组合。这是工作代码。

int fileds[2];
    int reading[num_cmds];
    int writing[num_cmds];

    int p;
    for(p=0; p < num_cmds; p++)
    {
        reading[p] = -1;
        writing[p] = -1;
    }

    int j;
    for(j=0; j < num_cmds-1; j++)
    {
        int fileds[2];
        pipe(fileds);
        reading[j+1] = fileds[0];
        writing[j] = fileds[1];
    }

    int i = 0;
    for(i = 0; i < num_cmds;i++)
    {           
        cmd_args = parse_cmd(cmds[i],output_file,input_file,&run_bg);

        pid_t childpid;
        int status;
        childpid=fork();

        if (childpid >= 0) 
        {
            if (childpid == 0) 
            {               
                if(writing[i] != -1)
                {
                    close(1);
                    dup2(writing[i],1);
                }

                if(reading[i] != -1)
                {
                    close(0);
                    dup2(reading[i],0);
                }

                if(execvp(cmd_args[0],cmd_args) == -1) 
                {
                    perror("Problem with command");
                    exit(0);
                }
            }
            else 
            {

                wait(&status);
                close(writing[i]);

                if(i > 0) 
                {
                    close(reading[i]);
                }
            }
        }
        else 
        {
             perror("fork");
        }


        input_file[0] = 0;
        output_file[0] = 0;
        run_bg = 0;
    }

2 个答案:

答案 0 :(得分:3)

我认为您的问题可能是等待循环内的每个进程然后关闭所有文件描述符。这使得文件描述符在下一次调用dup2()时无效,并导致stdin使下一个进程保持不变。

只是一个猜测,我没有运行代码。

答案 1 :(得分:0)

当我输入“ls | wc”时,wc按预期执行并打印ls命令输出的字数。请记住,当您使用“|”管道命令时您不需要在应用程序中创建管道。第一个命令需要输出到stdout,第二个命令需要从标准输入读取该输出。