C程序管道多个命令

时间:2016-08-28 06:12:47

标签: c linux fork dup2

我已经编写了下面的方法来fork和执行由多个管道分隔的命令(测试用:ls -lrt | grep" check" | wc -l。但是它没有产生任何输出,可以任何人请发现我的错误。谢谢。

   void execCmd (pInfo *info) 
{
  int i, j, k, m;
  struct comType *comm, *comm1, *comm2;
    if(info->noOfPipes > 2)
    {
        // DOES NOT WORK
        printf("Start\n");
        comm=&(info->cArr[0]);
        comm2=&(info->cArr[(info->ppNum)-1]);
        int fds[2];
        pipe(fds);
        pid_t pid = fork();
        if(pid == -1)
        {
            perror("fork failed");
            exit(1);
        }
        if(pid == 0)
        {
            printf("1st child execution here\n");
            close(fds[0]);
            dup2(fds[1], STDOUT_FILENO);
            close(fds[1]);
            execvp(comm->cmd,comm->parms);
        }
        for (k=1;k<=((info->ppNum)-1);k++)
        {
            printf("For loop executionn number %d",k);
            comm1=&(info->cArr[k]);
            printf ("comm 1 : %s\n",comm1->cmd);
            pid = fork();
            if(pid == -1)
            {
                perror("fork failed");
                exit(1);
            }
            if(pid == 0)
            {
                //2nd to n-1 child process
                dup2(fds[0], STDIN_FILENO);
                close(fds[0]);
                dup2(fds[1], STDOUT_FILENO);
                close(fds[1]);
                execvp(comm1->cmd,comm1->parms);
            }
            wait(NULL);
        }
        pid = fork();
        if(pid == -1)
        {
            perror("fork failed");
            exit(1);
        }
        if(pid == 0)
        {
            //nth child process
            printf("Last child execution\n");
            close(fds[1]);
            dup2(fds[0], STDIN_FILENO);
            close(fds[0]);
            execvp(comm2->cmd,comm2->parms);
        }
        close(fds[0]);
        close(fds[1]);
        wait(NULL);
        wait(NULL);
    }
}

1 个答案:

答案 0 :(得分:0)

以下代码应该让您了解如何实现流水线操作:

#define STDIN 0
#define STDOUT 1
void exec_cmd(struct comType cmd) {
    execvp(cmd->cmd, cmd->params);
}

void pipeCmds(struct comType* cmds) {
    int fd[cmds_length * 2] = {0};
    pid_t pid = 0;
    for (int i = 0; i < cmds_length; i++) {
        if (pid = fork() == 0) {
            //child: make this cmd's output the other cmd's input
            pipe(fd + (2*i) );
            close(STDOUT);
            dup(fd[i]);
            if(i > 0) {
                close(STDIN);
                dup(fd[i-1]);
            }
            exec_cmd(cmds[i]);
            close(fd[i]);           
        }
    }
}

请注意,主要想法是每个命令在一个单独的进程中执行(通过fork),输出转到下一个命令的输入而不是默认stdout(带文件描述符1),输入相同 - stdin(文件描述符0)。